Re: A couple of questions about goops method parameters
Taylan Ulrich Bayirli/Kammer taylanbayi...@gmail.com writes: Panicz Maciej Godek godek.mac...@gmail.com writes: [...] it's hard for me to see the advantage of FRP over OOP in practical systems (e.g. windowed applications with buttons and so on). [...] An off-topic remark: I don't know about *functional* reactive programming but from my experience so far as an iOS developer, I've been *longing* for a reactive programming system that automates state changes even if not fully hiding them. It would be invaluable being able to say button2.leftEdge = button1.rightEdge + 20px and have this equation be held automatically on changes to the layout of button1 (which might happen because it itself reacts to other layout changes), or to be able to say button.disabled = condition1 or condition2 and have the disabled status of button update automatically as the truthiness of the conditions changes. (The former use-case is actually covered by layout constraints, but that's strictly limited to layouting.) IIRC, Metafont does that; but obviously it isn't intended as a general language. Are there more general languages that solve equations like this? Regards, Neil
Re: A couple of questions about goops method parameters
Neil Jerram n...@ossau.homelinux.net writes: IIRC, Metafont does that; but obviously it isn't intended as a general language. Are there more general languages that solve equations like this? From what I know, Prolog. Other than that, Scheme. ;) Apart from David's FRP implementation, I worked on the following a little: https://gitorious.org/taylan-guile/reactive/ (Warning: I might force-push commits to that repo at times. It's not ready for consumption.) I don't consider it complete, and it might be broken. Some simple examples work: guile ,use (reactive base) guile (define x 0) guile (define v (make-value () x)) guile (define v2 (make-value (v) (display recalculated\n) (+ v 5))) guile (get/tainted v2) recalculated $2 = 5 guile (get/tainted v2) $3 = 5 guile (set! x 1) guile (taint! v) guile (get/tainted v2) recalculated $4 = 6 guile As you see, it's not purely-functional, and it requires explicit tainting of root values. After that, though, requesting any value which directly or indirectly depends on that root will ignite a recalculation of the graph of dependent values up to the requested one. I continuously get confused while trying to reason about the precise behavior of this system (even though it's very small), and had grave bugs in it at times (actually I just fixed one while writing this because I did a wholesale clean-up on the repo and re-uploaded it at the above link). Therefore, please don't trust that module for real usage. Taylan
Re: A couple of questions about goops method parameters
Marko Rauhamaa ma...@pacujo.net writes: It's perfectly fine to avoid errors by generalizing semantics so I wouldn't mind if you did what you propose. However, the dynamic type system is necessary for the simple fact that you will need to define runtime semantics. Oh, I was rather looking at things from a low-level perspective. E.g. the foo string in my example was meant as a pointer, whose numeric value plus 5 resulted in an integer whose underlying byte sequence is then interpreted as an IEEE double. In other words I was suggesting that by default there are only byte sequences, and type systems help to work with these conveniently. No, the primary objective is not to prevent errors but to have well-defined semantics. Scheme, Python, C or Java would function perfectly well without any type error checking, static or dynamic. The results could be undefined or a burning computer, that doesn't matter. What matters is that you know what a well-defined program is supposed to do. I think I understand your viewpoint, and it also makes sense: types might not be essential to bit-crunching, but they are to abstract models of computation. However, in my extensive practical experience, a static type system, [...] Does that experience cover languages like SML, Ocaml, and Haskell? (Not a rhetorical question, though I suspect it doesn't; at least not as much as languages like C, C++, and Java.) Taylan
Re: A couple of questions about goops method parameters
Taylan Ulrich Bayirli/Kammer taylanbayi...@gmail.com: Marko Rauhamaa ma...@pacujo.net writes: However, in my extensive practical experience, a static type system, [...] Does that experience cover languages like SML, Ocaml, and Haskell? I have had superficial experience with SML way back (late 80's). No idea how the languages would work in practice. However, I don't feel I'm missing anything in Scheme. (Not a rhetorical question, though I suspect it doesn't; at least not as much as languages like C, C++, and Java.) Not anywhere near as much. What do you have to say about those languages? Marko
Re: A couple of questions about goops method parameters
Marko Rauhamaa ma...@pacujo.net writes: Not anywhere near as much. What do you have to say about those languages? Just what I said previously: many users of languages with more sophisticated static type systems like Ocaml or Haskell say they prefer that over dynamic typing. I don't have much experience myself, though at times I also felt positive about the ability to encode some logic in a static type system. Taylan
Re: A couple of questions about goops method parameters
2014-09-06 0:14 GMT+02:00 Marko Rauhamaa ma...@pacujo.net: * [GOOPS] introduces a very strong, almost Linnaean, type system to Scheme, where it seems out of place. I see no principal reason for such classification. I don't declare my numbers in Scheme; why should I declare my object types? I don't think I understand. There is no strong type system, and there's no need to declare object types. The types are mainly for convinience -- to allow you to implement the same interfaces for different objects. The types are a great inconvenience, syntactically and conceptually. Syntactically, your GOOPS method de, it plainly extends the means of expression (and I think there's no problem in providing one's own syntax with a macro)finitions make your Scheme code look like Pascal with the class names sprinkled among the parameters. Conceptually, the classes force me to put objects into buckets that don't correspond to my thought processes. Even Java offers anonymous classes for the purpose. Now I don't understand what you're saying to even bigger extent. GOOPS does not offer a type system, but a multiple method dispatch system. It doesn't take away any freedom of using GOOPS objects with regular Scheme functions, but allows to use one interface for different implementations. Whether one likes the syntax or not, it plainly extends the means of expression (and I think there's no problem in providing one's own syntax with a macro) However, I'd rather say that the lack of any type system in Guile is an inconvinience, because static type checking allows to avoid a huge class of software errors, and a good type system (like the one in Haskell) actually enhances language's expressiveness. It's an issue that's been talked over so many times, that it's already present in comic strips: http://ro-che.info/ccc/17
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com writes: However, I'd rather say that the lack of any type system in Guile is an inconvinience, because static type checking allows to avoid a huge class of software errors, and a good type system (like the one in Haskell) actually enhances language's expressiveness. It's an issue that's been talked over so many times, that it's already present in comic strips: http://ro-che.info/ccc/17 I suspect that comic strip comes from someone who mostly witnessed silly flamewars between Haskellites with a higher-than-thou attitude, and CS unwary users of languages like JavaScript, Python, Ruby, etc. ;) In fact, the whole mention of a battle between the two groups, and showing zero overlap between the proponents of either strategy, tells me that the author is seriously misguided themselves. Maybe I'm reading too much into it, but what's at least obvious is that the author is a fan of Haskell. I'm sure that most serious Lispers and other CS-aware dynlang users are aware of the expressive power of good static type systems, and have respect for ML and Miranda descendants. However, I don't know of any hard evidence for the relevancy of the class of bugs prevented by static typing, given there is otherwise good program design and documentation. Only recently I met a static typing proponent who was merely spiteful against the horrible practices of some web developers (JavaScript users) they worked with... A good optional static type system could be neat for Guile, but not sure what priority this should have. (For now I would rather want sealed modules and the ability to static-import them into another.) Taylan
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com: However, I'd rather say that the lack of any type system in Guile is an inconvinience, because static type checking allows to avoid a huge class of software errors, and a good type system (like the one in Haskell) actually enhances language's expressiveness. We already have a satisfactory selection of languages with static type annotation. The primary upside of static types is much faster code. The downside is boilerplate and clutter that make it a huge chore to write and maintain the code. In my experience, high-level programming languages allow you to accomplish more challenging feats with better quality and productivity than statically typed languages. I'm saying use low-level programming languages when you have to and high-level programming languages when you can. Marko
Re: A couple of questions about goops method parameters
Marko Rauhamaa ma...@pacujo.net writes: The primary upside of static types is much faster code. Optimization of dynamic typing can go pretty far AFAIK. In an ideal case, type-checks are hoisted to outside critical sections of code and don't affect the speed of e.g. a tight loop. And then there's JIT and all that jazz... The downside is boilerplate and clutter that make it a huge chore to write and maintain the code. Users of languages with good static type systems like ML and Miranda descendants would rather argue that types make the program more maintainable, and aren't too much of a bother since they're inferred in many common cases. Not my own experience, but I have no reason for a wholesale disbelief against them (only skepticism on *how* great static typing is). In my experience, high-level programming languages allow you to accomplish more challenging feats with better quality and productivity than statically typed languages. I'm saying use low-level programming languages when you have to and high-level programming languages when you can. Using high-level/dynamically-typed, and low-level/statically-typed as synonyms seems pretty wrong. There are very low-level dynamically typed languages (Forth), and very high-level statically typed ones (Haskell). Taylan
Re: A couple of questions about goops method parameters
2014年9月6日 上午4:10于 Panicz Maciej Godek godek.mac...@gmail.com写道: dthomps...@worcester.edu: http://elm-lang.org/learn/What-is-FRP.elm Using FRP, we can model with mutable state in a pure, functional way. OTOH, when you take a look at the example code (Mario), you can trace the notion of objects. E.g. mario = { x = 0, y = 0, vx = 0, vy = 0, dir = right } What else is that, if not an object? Well, it's a structure, one could say -- because it has no methods. However, this is just what the most rudimentary GOOPS objects are -- a named tuple (provided that you use no virtual slots). I think that it is a big problem of Scheme, that it does not have any noncontroversial and commonly accepted way for creating named tuples. Doesn't assoc-list fill the gap? Furthermore, instead of using explicit side effects, as one would normally do, the Mario example first defines a step function, and calls foldp step mario input. Although I do appreciate efforts like in How to Design Worlds book or Introduction to Systematic Program Design course, to avoid explicit mutation (because as SICP shows, it complicates the model of computation), I don't see so many benefits of avoiding mutation in complex realtime systems. I partly agree with you. For stateless makes things complex. Yes, it could be complex. But, no, it depends on need and scenario. The advantage of stateless is to provide a more reliable and understandable system to users and maintainers. If your system is constrained by hard realtime need, go ahead with side-effect, it's cool. But most of the time, it's not the story from reasonable users. If you doubt stateless party exaggerated the truth, I'll recommend this paper: Out of the tar pit Actually, when I look at the Mario example, I have a feeling that the code would be much cleaner and easier to follow if it was written in a more traditional imperative/callback style. It's fine if you think imperative is still cool in FP, me too, since most people living in non-FP land. But if you're expecting imperative way in FP land rather than learning and trying it in FP way, why not choose non-FP lang for it? :-)
Re: A couple of questions about goops method parameters
2014-09-06 13:27 GMT+02:00 Marko Rauhamaa ma...@pacujo.net: Panicz Maciej Godek godek.mac...@gmail.com: However, I'd rather say that the lack of any type system in Guile is an inconvinience, because static type checking allows to avoid a huge class of software errors, and a good type system (like the one in Haskell) actually enhances language's expressiveness. We already have a satisfactory selection of languages with static type annotation. The primary upside of static types is much faster code. The downside is boilerplate and clutter that make it a huge chore to write and maintain the code. Taylan already wrote a few remarks on that statement. Obviously, when you're talking about statically typed languages, you mean C, Pascal, and its derivatives. However, you're mistaken. Haskell or ML are also statically typed, but because of type inference, they do not introduce any boilerplate nor clutter. The fact that C compiler performs static type checking has nothing to do with its performance. It's only about detecting type errors. So for example if you have code like: short f(); long g() { return f(); } the compiler will generate an error. An alternative would be to compile according to specification and let the user worry about the problems caused by type mismatch (and I think that this is what the early C compilers were doing) In my experience, high-level programming languages allow you to accomplish more challenging feats with better quality and productivity than statically typed languages. In addition to Taylan's remark, my experience is that in large programs it's very easy to make a type error, and it may take some time for that bug to manifest, and because of that latency such bugs become more confusing and harder to trace. Furthermore, having type signatures often make complex programs easier to read.
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com: The fact that C compiler performs static type checking has nothing to do with its performance. It's only about detecting type errors. So for example if you have code like: short f(); long g() { return f(); } the compiler will generate an error. (It actually doesn't. Try it.) You are right that C compilation would simply not be possible without static type information present. However, since Scheme can do everything C can without static type information, the principal justification for its existence is performance. That's why Guido van Rossum is tempted to add optional static type annotation to Python: it would make it possible replace Java/C# with Python. Marko
Re: A couple of questions about goops method parameters
Hi Nala, IMO, when you have lambda*, you never need define-method. Actually, I want to say, once you have such FP features, you don't need OOP anymore. I really don't see classes and multimethods a la CLOS competing against FP features. They are about certain ways of composing structures and providing common functional interfaces to them (and so, about certain ways of dispatching function calls). They don't promote mutability. They don't promote packaging data and methods in rigid ways. They just capture a pattern that would be cumbersome to implement by hand each time (even with the help of metaprogramming). I don't care about everything is an object stuff, but I do care about using the right tool for the problem at hand, and it feels good when the problem is a frequent one and the tool already exists. You can mix them while programming, but you don't have to. Anyway, if you try to avoid to use GOOPS someday, you have to handle dispatching by yourself. ;-) You see. There could be cases for which goops dispatching were not good enough, I can't say it for sure. But multimethods are an incredible flexible mechanism and you still have the mop to tweak, so I will write my own dispatching code and meta-code only as a last LAST resource. Best regards -- Carlos
Re: A couple of questions about goops method parameters
2014-09-05 10:32 GMT+02:00 Nala Ginrut nalagin...@gmail.com: Hi Carlos! On Tue, 2014-09-02 at 23:05 -0300, Carlos Pita wrote: 2) What is the relationship between the lambda* family and methods? Are methods restricted in the sense that they can't aspire to get the greater flexibility of lambda* parameter handling? Maybe because of the way dispatching is done? IMO, when you have lambda*, you never need define-method. Actually, I want to say, once you have such FP features, you don't need OOP anymore. So perhaps you could tell me how to design a GUI framework in FP and without OOP. To me it seems that GUI is the main domain the OOP was crafted for, but if you have some nice functional ideas, perhaps you could help me to redesign my framework. The base of the framework can be browsed here: https://bitbucket.org/panicz/slayer/src/94c9dde264759cbbd8d4a88d2581b77f55cc0bd6/guile-modules/widgets/base.scm?at=default What is particularly relevant is the widget class. I recently started creating my own OOP framework atop of GOOPS, so the same class could be equivalently written as https://bitbucket.org/panicz/slayer/src/94c9dde264759cbbd8d4a88d2581b77f55cc0bd6/guile-modules/extra/noobs.scm?at=default (see at the bottom) But I don't see any good alternative to OOP.
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com writes: So perhaps you could tell me how to design a GUI framework in FP and without OOP. To me it seems that GUI is the main domain the OOP was crafted for, but if you have some nice functional ideas, perhaps you could help me to redesign my framework. Are you familiar with functional reactive programming? http://elm-lang.org/learn/What-is-FRP.elm Using FRP, we can model with mutable state in a pure, functional way. That is, the necessary mutation is hidden behind the runtime of the FRP implementation. Just some food for thought. -- David Thompson Web Developer - Free Software Foundation - http://fsf.org GPG Key: 0FF1D807 Support the FSF: https://fsf.org/donate
Re: A couple of questions about goops method parameters
2014-09-05 21:12 GMT+02:00 David Thompson dthomps...@worcester.edu: Panicz Maciej Godek godek.mac...@gmail.com writes: So perhaps you could tell me how to design a GUI framework in FP and without OOP. To me it seems that GUI is the main domain the OOP was crafted for, but if you have some nice functional ideas, perhaps you could help me to redesign my framework. Are you familiar with functional reactive programming? http://elm-lang.org/learn/What-is-FRP.elm Using FRP, we can model with mutable state in a pure, functional way. That is, the necessary mutation is hidden behind the runtime of the FRP implementation. Just some food for thought. Sure, I've been reading a lot, but I didn't manage to get much of it. I mean, the toy examples are really nice, but it's hard for me to see the advantage of FRP over OOP in practical systems (e.g. windowed applications with buttons and so on). Although I see value in encapsulating state mutations, the notion of state seems inevitable in describing such applications (like the mere fact that a checkbox can be checked or not -- so it's a state which is a part of the description). BTW I recently ran into a problem with your signal propagation framework from (guile 2d). Namely, if a signal is itself a mutable object (like a vector or an array), then changing the value of that object doesn't propagate (because it happens only when you use slot-set!, and not (vector-set! (slot-ref ...)...)). I can't find any workaround for that.
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com writes: 2014-09-05 21:12 GMT+02:00 David Thompson dthomps...@worcester.edu: Panicz Maciej Godek godek.mac...@gmail.com writes: So perhaps you could tell me how to design a GUI framework in FP and without OOP. To me it seems that GUI is the main domain the OOP was crafted for, but if you have some nice functional ideas, perhaps you could help me to redesign my framework. Are you familiar with functional reactive programming? http://elm-lang.org/learn/What-is-FRP.elm Using FRP, we can model with mutable state in a pure, functional way. That is, the necessary mutation is hidden behind the runtime of the FRP implementation. Just some food for thought. Sure, I've been reading a lot, but I didn't manage to get much of it. I mean, the toy examples are really nice, but it's hard for me to see the advantage of FRP over OOP in practical systems (e.g. windowed applications with buttons and so on). Although I see value in encapsulating state mutations, the notion of state seems inevitable in describing such applications (like the mere fact that a checkbox can be checked or not -- so it's a state which is a part of the description). Yes, it's state, and state will always be there in a realtime application. However, you can still model it in a functional way with procedures that are idempotent and objects that are immutable. You just need to glue it all together with something that tracks the current state of the application. BTW I recently ran into a problem with your signal propagation framework from (guile 2d). Namely, if a signal is itself a mutable object (like a vector or an array), then changing the value of that object doesn't propagate (because it happens only when you use slot-set!, and not (vector-set! (slot-ref ...)...)). I can't find any workaround for that. I don't consider it a problem because the values stored signals are intended to be immutable. I will make that clear when I get around to documenting things better. If you mutate an object within the signal graph, bad things are bound to happen. The only reasonable side-effects are those that do not change values stored within signals, like writing to a log file or playing a sound. I have intentionally kept mutation at lowest layer of the system, abstracted away from the user. -- David Thompson Web Developer - Free Software Foundation - http://fsf.org GPG Key: 0FF1D807 Support the FSF: https://fsf.org/donate
Re: A couple of questions about goops method parameters
dthomps...@worcester.edu: http://elm-lang.org/learn/What-is-FRP.elm Using FRP, we can model with mutable state in a pure, functional way. OTOH, when you take a look at the example code (Mario), you can trace the notion of objects. E.g. mario = { x = 0, y = 0, vx = 0, vy = 0, dir = right } What else is that, if not an object? Well, it's a structure, one could say -- because it has no methods. However, this is just what the most rudimentary GOOPS objects are -- a named tuple (provided that you use no virtual slots). I think that it is a big problem of Scheme, that it does not have any noncontroversial and commonly accepted way for creating named tuples. Furthermore, instead of using explicit side effects, as one would normally do, the Mario example first defines a step function, and calls foldp step mario input. Although I do appreciate efforts like in How to Design Worlds book or Introduction to Systematic Program Design course, to avoid explicit mutation (because as SICP shows, it complicates the model of computation), I don't see so many benefits of avoiding mutation in complex realtime systems. Actually, when I look at the Mario example, I have a feeling that the code would be much cleaner and easier to follow if it was written in a more traditional imperative/callback style.
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com writes: [...] it's hard for me to see the advantage of FRP over OOP in practical systems (e.g. windowed applications with buttons and so on). [...] An off-topic remark: I don't know about *functional* reactive programming but from my experience so far as an iOS developer, I've been *longing* for a reactive programming system that automates state changes even if not fully hiding them. It would be invaluable being able to say button2.leftEdge = button1.rightEdge + 20px and have this equation be held automatically on changes to the layout of button1 (which might happen because it itself reacts to other layout changes), or to be able to say button.disabled = condition1 or condition2 and have the disabled status of button update automatically as the truthiness of the conditions changes. (The former use-case is actually covered by layout constraints, but that's strictly limited to layouting.) Declarative programming FTW. Taylan
Re: A couple of questions about goops method parameters
2014-09-05 22:18 GMT+02:00 Taylan Ulrich Bayirli/Kammer taylanbayi...@gmail.com: Panicz Maciej Godek godek.mac...@gmail.com writes: [...] I think that it is a big problem of Scheme, that it does not have any noncontroversial and commonly accepted way for creating named tuples. Does SRFI-9 not count because it creates tuple *types* and doesn't support immediate creation of tuples of an anonymous type? (Could be an interesting feature, though not sure how useful in the end.) Or do you just not consider SRFI-9 to be commonly accepted? AFAIK it's pretty widely implemented, and for the record(!) it's been standardized as a part of R7RS-small. There are a few issues here. The fact that it is impossible to create anonymous type is one thing. Another is that each record type introduces accessor bindings to a global namespace. In case of Elm, one could write mario = { x = 0, y = 0, dx = 0, dy = 0 } and then access the fields with the dot notation, i.e. mario.x There are other representations (like basket list or assoc list) that avoid that problem, but they generate other ones -- namely, that the access times get linear, and in case of assoc lists there is a huge overhead of data, and in case of basket lists one needs to pass around additional information regarding the names of subsequent fields. And the sole fact that there are other reasonable represetations leads to the conclusion that none is commonly accepted. (Actually I think the nicest solution I've seen was in Erlang, but unfortunately it wouldn't go well with Scheme)
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com: I think that it is a big problem of Scheme, that it does not have any noncontroversial and commonly accepted way for creating named tuples. That's what alists are. They may not be the most beautiful way to represent data as S expressions but they sure are noncontroversial and commonly accepted. However, objects, in my opinion, are the antithesis of tuples. Objects are the focal points of methods. Whether the black box contains data and in what form is none of the rest of the world's concern. IMO, GOOPS has two main flaws: * It brings an object's data slots to the fore while brushing methods aside. The object constructor syntax is more or less directly tied to the data slots. * It introduces a very strong, almost Linnaean, type system to Scheme, where it seems out of place. I see no principal reason for such classification. I don't declare my numbers in Scheme; why should I declare my object types? Marko
Re: A couple of questions about goops method parameters
Taylan Ulrich Bayirli/Kammer taylanbayi...@gmail.com writes: Panicz Maciej Godek godek.mac...@gmail.com writes: [...] it's hard for me to see the advantage of FRP over OOP in practical systems (e.g. windowed applications with buttons and so on). [...] An off-topic remark: I don't know about *functional* reactive programming but from my experience so far as an iOS developer, I've been *longing* for a reactive programming system that automates state changes even if not fully hiding them. It would be invaluable being able to say button2.leftEdge = button1.rightEdge + 20px and have this equation be held automatically on changes to the layout of button1 (which might happen because it itself reacts to other layout changes), or to be able to say button.disabled = condition1 or condition2 and have the disabled status of button update automatically as the truthiness of the conditions changes. (The former use-case is actually covered by layout constraints, but that's strictly limited to layouting.) In my reactive programming system, you could say: (define-signal button2-left-edge (signal-map (cut + 20) button1-right-edge)) Which is, of course, more verbose than your example. I want to explore creating a macro that would abstract away the unboxing of signals so I could simply write... (define-signal button-2-left-edge (+ button1-right-edge 20)) ... and it would DTRT. Racket's FrTime can do this, which is neat. Declarative programming FTW. Agreed. :) -- David Thompson Web Developer - Free Software Foundation - http://fsf.org GPG Key: 0FF1D807 Support the FSF: https://fsf.org/donate
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com: There are other representations (like basket list or assoc list) that avoid that problem, but they generate other ones -- namely, that the access times get linear, and in case of assoc lists there is a huge overhead of data, and in case of basket lists one needs to pass around additional information regarding the names of subsequent fields. Dynamic programming languages lack a true, efficient dot notation. That's a price I'm willing to pay (especially since Guile allows me to switch to C where necessary). For example, Python and JavaScript translate x.f into a hash table lookup. In my tests, Guile's alists are more efficient than hash tables up to maybe a hundred elements or so (IIRC). That's why I switched to alists in my tiny object system. As for the data overhead, I haven't yet really run into that problem. Again, high memory use is a common issue with dynamic programming languages. Python's objects are quite sizable as well. Marko
Re: A couple of questions about goops method parameters
2014-09-05 22:44 GMT+02:00 Marko Rauhamaa ma...@pacujo.net: Panicz Maciej Godek godek.mac...@gmail.com: I think that it is a big problem of Scheme, that it does not have any noncontroversial and commonly accepted way for creating named tuples. That's what alists are. They may not be the most beautiful way to represent data as S expressions but they sure are noncontroversial and commonly accepted. I think that (putting side other issues) if one person in this thread claims that srfi-9 is a commonly accepted representation, and another claims that alists are a a commonly accepted representation, then it's a proof that none is commonly accepted. However, objects, in my opinion, are the antithesis of tuples. Objects are the focal points of methods. Whether the black box contains data and in what form is none of the rest of the world's concern. Apparently our views on the essence of OOP differ. I perceive an object as an aggregation of properties, and a set of methods I would call an interface. Perhaps to you doing OOP is about defining interfaces, and to me it's more about aggregating properties. I wouldn't say that anyone of us is more right than the other. IMO, GOOPS has two main flaws: * It brings an object's data slots to the fore while brushing methods aside. The object constructor syntax is more or less directly tied to the data slots. I agree that the constructor syntax isn't expressible to handle some very common use cases, and requires to overload the initialize method in many trivial situations. But my solution to this problem is to construct OOP framework atop of GOOPS. It might not be the simplest solution, but I find it promising * It introduces a very strong, almost Linnaean, type system to Scheme, where it seems out of place. I see no principal reason for such classification. I don't declare my numbers in Scheme; why should I declare my object types? I don't think I understand. There is no strong type system, and there's no need to declare object types. The types are mainly for convinience -- to allow you to implement the same interfaces for different objects.
Re: A couple of questions about goops method parameters
Marko Rauhamaa ma...@pacujo.net writes: Dynamic programming languages lack a true, efficient dot notation. If with a true, efficient dot notation you mean for example C structs, then records fill that role except for using accessor procedures instead of syntax. (Under the right conditions, usage of records could compile to direct O(1) memory access (pointer+offset), just like usage of vectors. Arrays and structs in C are in direct analogy to vectors and records in Scheme; the only difference being Scheme's general requirement of type-checks.) Though after pondering a bit I realized that it indeed seems impossible to compile (.bar foo) (could result from foo[.bar] via SRFI-105) into the correct memory offset, if there are multiple record types each with a '.bar' field, because it's not statically known which record type 'foo' has. Maybe that's exactly what you meant. Taylan
Re: A couple of questions about goops method parameters
Panicz Maciej Godek godek.mac...@gmail.com: 2014-09-05 22:44 GMT+02:00 Marko Rauhamaa ma...@pacujo.net: However, objects, in my opinion, are the antithesis of tuples. Objects are the focal points of methods. Whether the black box contains data and in what form is none of the rest of the world's concern. Apparently our views on the essence of OOP differ. I perceive an object as an aggregation of properties, and a set of methods I would call an interface. Perhaps to you doing OOP is about defining interfaces, and to me it's more about aggregating properties. I wouldn't say that anyone of us is more right than the other. There's no point arguing about terminology. All I want to say is that my OOP is desirable to me, your OOP is something I want to steer away from. I don't need interfaces as first-class entities in an object system. Ducktyping involves less clutter and is more generic. * [GOOPS] introduces a very strong, almost Linnaean, type system to Scheme, where it seems out of place. I see no principal reason for such classification. I don't declare my numbers in Scheme; why should I declare my object types? I don't think I understand. There is no strong type system, and there's no need to declare object types. The types are mainly for convinience -- to allow you to implement the same interfaces for different objects. The types are a great inconvenience, syntactically and conceptually. Syntactically, your GOOPS method definitions make your Scheme code look like Pascal with the class names sprinkled among the parameters. Conceptually, the classes force me to put objects into buckets that don't correspond to my thought processes. Even Java offers anonymous classes for the purpose. Marko
Re: A couple of questions about goops method parameters
Taylan Ulrich Bayirli/Kammer taylanbayi...@gmail.com: Though after pondering a bit I realized that it indeed seems impossible to compile (.bar foo) (could result from foo[.bar] via SRFI-105) into the correct memory offset, if there are multiple record types each with a '.bar' field, because it's not statically known which record type 'foo' has. Maybe that's exactly what you meant. Yes. It is amusing, though, that C originally suffered from the same issue: the struct field offsets were global linker objects. That's why to this day, unix/linux C structs have ugly field prefixes: struct timeval { time_t tv_sec; suseconds_t tv_usec; }; struct timezone { int tz_minuteswest; int tz_dsttime; }; struct linger { int l_onoff; int l_linger; }; struct sockaddr_in { sa_family_tsin_family; in_port_t sin_port; struct in_addr sin_addr; }; struct in_addr { uint32_t s_addr; }; struct iovec { void *iov_base; size_t iov_len; }; and so on... Marko
Re: A couple of questions about goops method parameters
directly call initialize? In any case, why is this so? Wouldn't it be better for initialize to just get the unpacked argument list? This perplexes me. I've been thinking about this, and lurking at the tinyclos implementation, and then reading the cltl sections about initialization in clos. Despite the fact that clos make-instance indeed *apply* the initargs when calling initialize-instance, thus unpacking/destructuring the initargs list, everything in the specification seems to imply a plist style of usage. Even the name part of a name-value pair is used to choose between (i) direct initialization of the corresponding slot or (ii) calling the initialize-instance method with the name-value pair. So, all in all, the usage implied is akin to dealing with a (name value name value ...) list argument in goops or tinyclos. All this seems specifically oriented to slot initialization, not to general construction of a new instance while preserving some class invariant imposed to the internal data/slots (please, notice that my interest here is not about encapsulation or access control matters). So maybe I'm suffering from a paradigm mismatch kind of thing, as I'm trying to fit initialize into the usual OOP concept of constructor. From this perspective initialize (and initialize-instance) looks to me like erotic lingerie for slots (no pun intended, really :)), as maybe it isn't completely transparent but it's surely translucent regarding the underlying slots. The focus seems to be at a lower level of abstraction than the level the usual constructor operates in. I'm aware of virtual slots and, of course, of the possibility of implementing a custom initialize method, but these solutions only buy some degrees of freedom around the slot initializing focus: virtual slots still looks like slots and the argument to initialize is still a list, presumably of slot name-value pairs. I'm also aware of the possibility of defining read only slots but, again, this is not generally enough to offer convenient ways of construction that preserve some desired invariant. So, a question to the experienced lispers here, a question that's not specifically guile or goops or scheme related. Is the make (or make-instance) way of constructing a new instance usually exposed to the final user? Or a factory function, operating at a higher level of abstraction, is intended to wrap the lower level, slot-fillig oriented, call to make? In this case, a custom initialize method implementation should be seen more as a complement to make than as a proper constructor/factory. (Moreover, the visibility and access of constructor/factory functions are easily controlled using the module system although, as I've said before, that's not my interest here). Best regards -- Carlos
Re: A couple of questions about goops method parameters
Howdy, How do you typically implement a custom initialization method, then? Using pattern matching? Maybe ice-9 optargs? Maybe apply? Maybe you directly call initialize? In any case, why is this so? Wouldn't it be better for initialize to just get the unpacked argument list? This perplexes me. I'm not sure if I get the question right, but you usually overload the initialize method (which calls (next-method)) and use the let-keywords form if you want to add additional initialization parameters 2) What is the relationship between the lambda* family and methods? Are methods restricted in the sense that they can't aspire to get the greater flexibility of lambda* parameter handling? Maybe because of the way dispatching is done? This is a good question and I'd like to know the answer myself, but it seems to me that GOOPS methods and keyword arguments are simply incompatible. Obviously you can obtain default arguments in GOOPS quite easily: (define-method (f (x t1) (y t2)) ...) (define-method (f (x t1)) (f x default-y-value)) (define-method (f) (f default-x-value)) One could also come up easily with a macro that allows to expand (define-method/default (f (x t1 default-x-value) (y t2 default-y-value)) ...) to the above code. But I don't think that the goops dispatcher was anyhow suited for the keyword arguments (I could be wrong, though)
Re: A couple of questions about goops method parameters
Carlos Pita carlosjosep...@gmail.com: So, a question to the experienced lispers here, a question that's not specifically guile or goops or scheme related. Is the make (or make-instance) way of constructing a new instance usually exposed to the final user? Or a factory function, operating at a higher level of abstraction, is intended to wrap the lower level, slot-fillig oriented, call to make? In this case, a custom initialize method implementation should be seen more as a complement to make than as a proper constructor/factory. I saw the light and left goops behind. I built a simple system: * Not slot-centric but method-centric. * No classes, only objects. IMO, the end result is more schemey than Goops. It contains: (make-object parentage . methods) where parentage is #f, an object or a list of objects methods contains procedures, or name-procedure pairs Example: (define (point .x .y) (define (x) .x) (define (y) .y) (make-object #f x y)) (let ((point (point 7 8))) (point #:y)) = 8 Marko
Re: A couple of questions about goops method parameters
http://www.aiai.ed.ac.uk/~jeff/clos-guide.html and http://permalink.gmane.org/gmane.lisp.cl-pro/24 support the make as implementation detail view. Some excerpts: It's often a good idea to define your own constructor functions, rather than call make-instance directly, because you can hide implementation details and don't have to use keyword parameters for everything. For instance, if you wanted the name and age to be required, positional parameters, rather than keyword parameters, you could define (defun make-person (name age) (make-instance 'person :name name :age age)) [Notice how more convolved implementing the same using initialize would be] - In addition to this, you'd use a factory function, rather than having the client call make-instance, to hide the CLOS nature of the type. On Sep 3, 2014 1:47 PM, Marko Rauhamaa ma...@pacujo.net wrote: Carlos Pita carlosjosep...@gmail.com: So, a question to the experienced lispers here, a question that's not specifically guile or goops or scheme related. Is the make (or make-instance) way of constructing a new instance usually exposed to the final user? Or a factory function, operating at a higher level of abstraction, is intended to wrap the lower level, slot-fillig oriented, call to make? In this case, a custom initialize method implementation should be seen more as a complement to make than as a proper constructor/factory. I saw the light and left goops behind. I built a simple system: * Not slot-centric but method-centric. * No classes, only objects. IMO, the end result is more schemey than Goops. It contains: (make-object parentage . methods) where parentage is #f, an object or a list of objects methods contains procedures, or name-procedure pairs Example: (define (point .x .y) (define (x) .x) (define (y) .y) (make-object #f x y)) (let ((point (point 7 8))) (point #:y)) = 8 Marko
A couple of questions about goops method parameters
Hi all, I've some questions about parameter handling in goops methods: 1) initialize takes the initargs argument as a list, because of the way make-instance is defined. But the documentation states: In theory, initarg … can have any structure that is understood by whatever methods get applied when the initialize generic function is applied to the newly allocated instance. One could think this implies that initargs won't necessarily be packed as a list. Indeed, that would be very convenient and sensible for custom initialization methods. But make-instance is implemented as: (define-method (make-instance (class class) . initargs) (let ((instance (allocate-instance class initargs))) (initialize instance initargs) instance)) So one would need to rewrite it in order to apply initargs, or something like that, in order to unpack the list. How do you typically implement a custom initialization method, then? Using pattern matching? Maybe ice-9 optargs? Maybe apply? Maybe you directly call initialize? In any case, why is this so? Wouldn't it be better for initialize to just get the unpacked argument list? This perplexes me. 2) What is the relationship between the lambda* family and methods? Are methods restricted in the sense that they can't aspire to get the greater flexibility of lambda* parameter handling? Maybe because of the way dispatching is done? Thank you very much in advance for any help. Best regards -- Carlos