* Re: Article about GNU Guile and GOOPS
2014-03-04 14:03 ` Thompson, David
@ 2014-03-04 15:16 ` Panicz Maciej Godek
2014-03-04 18:00 ` Jan Wedekind
2014-03-05 18:12 ` Interesting project proposal for generics in Racket Jan Wedekind
2014-03-04 17:41 ` Article about GNU Guile and GOOPS Jan Wedekind
2014-03-05 11:28 ` Nala Ginrut
2 siblings, 2 replies; 12+ messages in thread
From: Panicz Maciej Godek @ 2014-03-04 15:16 UTC (permalink / raw)
To: Thompson, David; +Cc: General Guile related discussions
Hello everybody,
2014-03-04 13:57 GMT+01:00 Jan Wedekind <jan@wedesoft.de>:
[...]
> It took me a while to figure out defining constructors and dynamic
> instantiation of OO primitives. I hope it'll save somebody else some time
> one day.
Well, I think that I'm a similar case -- it also took me a while how
to define constructors. Perhaps patching a GOOPS manual would be a
more effective solution.
> Any comments and suggestions are welcome.
I'm really glad that the topic has finally been touched. However, I
didn't find the metaclass part particularly useful -- I think it would
be more valuable, if there were some real-life applications of
metaclasses presented, or if there was just a link to the proper
section of the GOOPS manual instead of the whole section on
metaclasses (because it doens't make the text any clearer).
What I find lacking is a criticism, or at least some reference to the
more contemporary approaches to OOP (such as Ruby or Python or Java).
I have been using GOOPS quite extensively, and I personally find it a
little controversial. For one, because there's no standard and
portable OOP framework for Scheme. This lack of portability is of a
big concern to me.
Besides, I think that Scheme + OOP has its own flaws. In most OOP
languages, you have this notation object.property or object->method(),
which also allows for chain calls, i.e. object->getChild()->method(),
or -- if you have nested objects -- to use
object.property.propertys_property.
If you want to obtain a uniform access to slots (i.e. without the
#:getter and #:setter -- which are a surprising way of introducing new
definitions to a module), you need to use slot-ref and slot-set!. This
quickly becomes horrible when you have nested calls:
(slot-ref (slot-ref object 'property) 'propertys-property)
[The same applies to vectors, arrays, hash tables and other stuff].
I managed to create a workaround (using the GOOPS multi-method
dispatch, read-hash-extend and procedure-with-setter) that allows me
to write
#[object 'property]
and
#[object : 'property : 'propertys-property]
(it also supports vectors and hashes and so on) and although it helps
a little, I'm not particularly happy with that solution.
It is available here, if anyone's interested:
http://hg.gnu.org.ua/hgweb/slayer/file/d5302c97b90d/guile-modules/extra/ref.scm
2014-03-04 15:03 GMT+01:00 Thompson, David <dthompson2@worcester.edu>:
[...]
>
> I think it's a nice little introduction to GOOPS.
>
> I want to discuss this particular point from the post, because it is
> shared by many other people: "... one thing I don't like about Scheme
> is that there are different function names for each type of arguments.
> E.g. adding numbers is done with +, adding lists is done with append,
> and adding strings is done with string-append."
On the contrary, I'm actually rather unhappy that you need functions
like hash-for-each or vector-map or string-append in order to express
a single concept. (To be honest, I hope that one day explicit hash
tables, strings and vectors would disappear from Scheme, and there'll
only be lists, because they bring nothing new conceptually and are
there only for sake of efficiency)
> Having spent many years now working with object oriented programming
> languages, I hold the opposite opinion. I think it's awkward to have
> a single '+' operator for all sorts of different operations on many
> different types. Adding numbers is different than concatenating
> strings or lists and using the same symbol for them leads to
> confusion. Look at JavaScript for all of the crazy things that happen
> when you add together different types of data: The expression 1 +
> "foo" returns "1foo"! [] + {} returns "[object Object]"! WTF? Ruby
> tends to be a bit more sane in this regard, but I think the point
> still stands that operator overloading leads to confusion and strange
> behavior.
>
> WDYT?
I think that it is different in that JavaScript's addition operator
performs an implicit cast, while CLOS-alike methods allow you to
specialize your function for various types of arguments, so you'll
simply get an error if you don't implement "+" for <number> and
<string>.
And although it might seem a little bit risky, I like to have the
option of using the same name for different concepts and still have a
system behave reasonably, because that's basically how natural
language works (which is full of homonyms, like "like"). On the other
hand, I have to admit that the module system in Guile is excellent at
separating concepts from different domains, even if their names are
the same.
What I find more disturbing is that there is no possibility to specify
a type for a particular slot, but this is a broader topic.
regards
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Article about GNU Guile and GOOPS
2014-03-04 15:16 ` Panicz Maciej Godek
@ 2014-03-04 18:00 ` Jan Wedekind
2014-03-04 21:17 ` Yawar Amin
2014-03-05 18:12 ` Interesting project proposal for generics in Racket Jan Wedekind
1 sibling, 1 reply; 12+ messages in thread
From: Jan Wedekind @ 2014-03-04 18:00 UTC (permalink / raw)
To: Panicz Maciej Godek; +Cc: General Guile related discussions, Thompson, David
On Tue, 4 Mar 2014, Panicz Maciej Godek wrote:
> Hello everybody,
>
> 2014-03-04 13:57 GMT+01:00 Jan Wedekind <jan@wedesoft.de>:
> [...]
>> It took me a while to figure out defining constructors and dynamic
>> instantiation of OO primitives. I hope it'll save somebody else some time
>> one day.
>
> Well, I think that I'm a similar case -- it also took me a while how
> to define constructors. Perhaps patching a GOOPS manual would be a
> more effective solution.
>
>> Any comments and suggestions are welcome.
>
> I'm really glad that the topic has finally been touched. However, I
> didn't find the metaclass part particularly useful -- I think it would
> be more valuable, if there were some real-life applications of
> metaclasses presented, or if there was just a link to the proper
> section of the GOOPS manual instead of the whole section on
> metaclasses (because it doens't make the text any clearer).
Hi, I'll think about it if I find an example which motivates that better.
Maybe I'll add a comparison to how Ruby does it. Java, Ruby, C++, and
Python all let you define static methods, i.e. metaclasses are defined
implicitely.
> What I find lacking is a criticism, or at least some reference to the
> more contemporary approaches to OOP (such as Ruby or Python or Java).
Ok, thanks for the feedback.
> I have been using GOOPS quite extensively, and I personally find it a
> little controversial. For one, because there's no standard and
> portable OOP framework for Scheme. This lack of portability is of a
> big concern to me.
Yes. However once you have a standard portable OOP framework, you will
face the evolution dilemma: If you change the software, you risk loosing
stakeholders in the short term. If you avoid change, you will be
outcompeted in the long term.
> Besides, I think that Scheme + OOP has its own flaws. In most OOP
> languages, you have this notation object.property or object->method(),
> which also allows for chain calls, i.e. object->getChild()->method(),
> or -- if you have nested objects -- to use
> object.property.propertys_property.
>
> If you want to obtain a uniform access to slots (i.e. without the
> #:getter and #:setter -- which are a surprising way of introducing new
> definitions to a module), you need to use slot-ref and slot-set!. This
> quickly becomes horrible when you have nested calls:
> (slot-ref (slot-ref object 'property) 'propertys-property)
> [The same applies to vectors, arrays, hash tables and other stuff].
> I managed to create a workaround (using the GOOPS multi-method
> dispatch, read-hash-extend and procedure-with-setter) that allows me
> to write
> #[object 'property]
> and
> #[object : 'property : 'propertys-property]
> (it also supports vectors and hashes and so on) and although it helps
> a little, I'm not particularly happy with that solution.
> It is available here, if anyone's interested:
>
> http://hg.gnu.org.ua/hgweb/slayer/file/d5302c97b90d/guile-modules/extra/ref.scm
I think that's a good point. AFAIK in Clojure they have a notation for
chaining method calls, too.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Article about GNU Guile and GOOPS
2014-03-04 18:00 ` Jan Wedekind
@ 2014-03-04 21:17 ` Yawar Amin
0 siblings, 0 replies; 12+ messages in thread
From: Yawar Amin @ 2014-03-04 21:17 UTC (permalink / raw)
To: Jan Wedekind; +Cc: General Guile related discussions, Thompson, David
Hi,
On 2014-03-04, at 13:00, Jan Wedekind <jan@wedesoft.de> wrote:
> On Tue, 4 Mar 2014, Panicz Maciej Godek wrote:
>
>> [...]
>> #[object 'property]
>> and
>> #[object : 'property : 'propertys-property]
>> (it also supports vectors and hashes and so on) and although it helps
>> a little, I'm not particularly happy with that solution.
>> It is available here, if anyone's interested:
>>
>> http://hg.gnu.org.ua/hgweb/slayer/file/d5302c97b90d/guile-modules/extra/ref.scm
> I think that's a good point. AFAIK in Clojure they have a notation for chaining method calls, too.
Clojure has the thread-last macro ('->>'), which lets you do:
(->> object property propertys-property)
Greg Hendershott has, I think, ported it to Racket. It should work well with accessor functions which is I think how Goops works, correct me if I'm wrong.
Regards,
Yawar
^ permalink raw reply [flat|nested] 12+ messages in thread
* Interesting project proposal for generics in Racket
2014-03-04 15:16 ` Panicz Maciej Godek
2014-03-04 18:00 ` Jan Wedekind
@ 2014-03-05 18:12 ` Jan Wedekind
2014-03-08 9:40 ` Panicz Maciej Godek
1 sibling, 1 reply; 12+ messages in thread
From: Jan Wedekind @ 2014-03-05 18:12 UTC (permalink / raw)
To: Panicz Maciej Godek; +Cc: General Guile related discussions, Thompson, David
> Besides, I think that Scheme + OOP has its own flaws. In most OOP
> languages, you have this notation object.property or object->method(),
> which also allows for chain calls, i.e. object->getChild()->method(),
> or -- if you have nested objects -- to use
> object.property.propertys_property.
Somewhat related I have seen an interesting project proposal for generics
in Racket [1]. The generics use predicate functions instead of classes.
E.g.:
(defmethod add ((x number?) (y number?))
(+ (x y))
where 'number?' is a function returning '#t' for numbers.
The type hierarchy (specialisation) is declared using 'defsubtype'. E.g.:
(defsubtype zero? integer?)
This facilitates defining factorial like this:
(defgeneric fact (n))
(defmethod fact ((n integer?)) (* n (fact (- n 1))))
(defmethod fact ((n zero?)) 1)
Regards
Jan
[1] https://fenix.tecnico.ulisboa.pt/downloadFile/3779579671692/project.pdf
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Interesting project proposal for generics in Racket
2014-03-05 18:12 ` Interesting project proposal for generics in Racket Jan Wedekind
@ 2014-03-08 9:40 ` Panicz Maciej Godek
0 siblings, 0 replies; 12+ messages in thread
From: Panicz Maciej Godek @ 2014-03-08 9:40 UTC (permalink / raw)
To: Jan Wedekind; +Cc: General Guile related discussions, Thompson, David
2014-03-05 19:12 GMT+01:00 Jan Wedekind <jan@wedesoft.de>:
>> Besides, I think that Scheme + OOP has its own flaws. In most OOP
>> languages, you have this notation object.property or object->method(),
>> which also allows for chain calls, i.e. object->getChild()->method(),
>> or -- if you have nested objects -- to use
>> object.property.propertys_property.
>
> Somewhat related I have seen an interesting project proposal for generics in
> Racket [1]. The generics use predicate functions instead of classes. E.g.:
>
> (defmethod add ((x number?) (y number?))
> (+ (x y))
>
> where 'number?' is a function returning '#t' for numbers.
>
> The type hierarchy (specialisation) is declared using 'defsubtype'. E.g.:
>
> (defsubtype zero? integer?)
I don't know whether it's better to provide a separate entity for
types/classes or to use bare predicates. I think that an advantage of
explicit first class types (such as the ones used in GOOPS) is that
one could easily provide a method to generate exemplars of objects of
those types, which could be useful for unit tests performed by systems
such as QuickCheck.
I think it should be fairly easy to implement such system portably for
Scheme. Even better, I believe it would be nice to employ the
Wright-Shinn pattern matcher (known as (ice-9 match) for Guilers) in
signatures of functions, so that one could write e.g.
(generic factorial)
(specialize (factorial 0) 1)
(specialize (factorial (? number? n)) (* n (factorial (- n 1)))
[I am using the name 'specialize' here in order to avoid confuision,
but the concept is the same]
It's a nice idea to stipulate the ordering relation for predicates
(although it obviously would be better if the interpreter could infer
it automatically, at least to some extent). What would be needed for
the "match"-based implementation is a partial order of the "match"
patterns, so that they could be ordered from the most specific to the
least specific (which seems an interesting issue by itself).
It would also be nice if that could integrate with a full-blown type
system, so that apart from types for arguments, one could declare
types for the values being returned by a function, and if a tool for
static type analysis could be provided, because that would allow to
increase the type-safety of Scheme programs.
But I agree that this is an interesting and important issue.
Best regards,
M.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Article about GNU Guile and GOOPS
2014-03-04 14:03 ` Thompson, David
2014-03-04 15:16 ` Panicz Maciej Godek
@ 2014-03-04 17:41 ` Jan Wedekind
2014-03-05 11:28 ` Nala Ginrut
2 siblings, 0 replies; 12+ messages in thread
From: Jan Wedekind @ 2014-03-04 17:41 UTC (permalink / raw)
To: Thompson, David; +Cc: General Guile related discussions
On Tue, 4 Mar 2014, Thompson, David wrote:
> On Tue, Mar 4, 2014 at 7:57 AM, Jan Wedekind <jan@wedesoft.de> wrote:
>> Hi,
>> I have written a small blog post about object-oriented programming with
>> GNU Guile and GOOPS [1]. Having used the Ruby programming language for some
>> time, I am quite spoiled when it comes to objects ;)
>> It took me a while to figure out defining constructors and dynamic
>> instantiation of OO primitives. I hope it'll save somebody else some time
>> one day.
>> Any comments and suggestions are welcome.
>>
>> Regards
>> Jan
>>
>> [1] http://wedesoft.de/oop-with-goops.html
>
> Hi Jan,
>
> I think it's a nice little introduction to GOOPS.
>
> I want to discuss this particular point from the post, because it is
> shared by many other people: "... one thing I don't like about Scheme
> is that there are different function names for each type of arguments.
> E.g. adding numbers is done with +, adding lists is done with append,
> and adding strings is done with string-append."
>
> Having spent many years now working with object oriented programming
> languages, I hold the opposite opinion. I think it's awkward to have
> a single '+' operator for all sorts of different operations on many
> different types. Adding numbers is different than concatenating
> strings or lists and using the same symbol for them leads to
> confusion. Look at JavaScript for all of the crazy things that happen
> when you add together different types of data: The expression 1 +
> "foo" returns "1foo"! [] + {} returns "[object Object]"! WTF? Ruby
> tends to be a bit more sane in this regard, but I think the point
> still stands that operator overloading leads to confusion and strange
> behavior.
>
> WDYT?
>
> - Dave
>
>
Hi,
I agree, I wouldn't define 1+"foo" or []+{} (and I haven't done so in my
article). I guess you have the "WAT" talk [2] at "Destroy all Software"
in mind ;)
I think that GOOPS makes sense because without being able to extend '+',
user-defined numeric classes (e.g. hypercomplex numbers) always would be
second class citizens compared to Guile's integers, floating point
numbers, and complex numbers.
Anyway, I need to collect some experience with this in Scheme myself.
But I hope it will work out well.
Regards
Jan
[2] https://www.destroyallsoftware.com/talks/wat
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Article about GNU Guile and GOOPS
2014-03-04 14:03 ` Thompson, David
2014-03-04 15:16 ` Panicz Maciej Godek
2014-03-04 17:41 ` Article about GNU Guile and GOOPS Jan Wedekind
@ 2014-03-05 11:28 ` Nala Ginrut
2 siblings, 0 replies; 12+ messages in thread
From: Nala Ginrut @ 2014-03-05 11:28 UTC (permalink / raw)
To: Thompson, David; +Cc: General Guile related discussions
> I think it's a nice little introduction to GOOPS.
>
> I want to discuss this particular point from the post, because it is
> shared by many other people: "... one thing I don't like about Scheme
> is that there are different function names for each type of arguments.
> E.g. adding numbers is done with +, adding lists is done with append,
> and adding strings is done with string-append."
>
> Having spent many years now working with object oriented programming
> languages, I hold the opposite opinion. I think it's awkward to have
> a single '+' operator for all sorts of different operations on many
> different types. Adding numbers is different than concatenating
> strings or lists and using the same symbol for them leads to
> confusion. Look at JavaScript for all of the crazy things that happen
> when you add together different types of data: The expression 1 +
> "foo" returns "1foo"! [] + {} returns "[object Object]"! WTF? Ruby
> tends to be a bit more sane in this regard, but I think the point
> still stands that operator overloading leads to confusion and strange
> behavior.
>
Agreed, how about "1"+"2" == "12"
I think it's illogical to understand such a program. Of course, this
equation is too simple, my intention is to explain why a unified method
for various objects looks ridiculous.
But sometimes we do need a generic way to handle various objects with
hiding the details. There're several ways for this purpose in Scheme to
abstract higher data-representation in some well known approaches. So
one may design a generic function to handle various objects well.
This topic was discussed profoundly in Chapter 2 of SICP, so I don't nag
anymore. ;-)
My opinion is that we don't have to pick the tools from OOP. But some
people may argue that these approaches are actually building a
half-baked OO-system in your code.
After using GOOPS for a while, I begin to think why we need OO, but I
can't get a conclusion so far. I'm not saying GOOPS is worthless. I want
to raise a discussion about "Is OO necessary for Scheme?"
In spite of generic functions I've mentioned above, there's also
lambda*, which could be both treated as solution for polymorphism. I
realized that we don't need the classical Class too. Because the
record-type in R6Rs is more powerful, it even supports inheritance!
Encapsulation? Maybe the only problem is that we don't have strictly
private symbols, which means there's always a way to touch un-exported
symbols from modules.
But we can specify immutable fields in R6Rs type-record, which can
protect the value. My understanding is that people don't really want to
make a field hidden, they just don't want it to be changed occasionally,
so we don't need strictly private feature, no?
I confess there's an exception if you want to modify the immutable field
from a 'friend type-record' just like 'friend class', and prevent
others. But I don't know the code context why people need it.
I guess most of the essentials of OOP are covered. I'd like to hear
comments from folks. ;-)
WDYT?
^ permalink raw reply [flat|nested] 12+ messages in thread