From transfire at gmail.com Thu Sep 1 11:32:10 2005 From: transfire at gmail.com (TRANS) Date: Thu Sep 1 11:25:26 2005 Subject: [suby-talk] Truly Private Methods In-Reply-To: References: <4b6f054f0508251014524bdf9a@mail.gmail.com> <4b6f054f05082603576022fb11@mail.gmail.com> <4b6f054f05082714374698bf3b@mail.gmail.com> <4b6f054f050829074423c6c3c7@mail.gmail.com> <4b6f054f0508300807f6eff01@mail.gmail.com> Message-ID: <4b6f054f05090108327df0438f@mail.gmail.com> Thinking about your namespace idea and had a thought. Presently one can define a "meta" method: class X def self.x ; ... ; end end Or as singleton on an object. o = Object.new def o.x ; ... ; end I wonder if it can be extended to autovivify to a namspace if an object of that name doesn't exist? class X def o.x ; ... ; end end Also, does that mean a namespace is a class? class Namespace initialize( obj ) self = obj # not possible but if end end T. From calamitas at advalvas.be Thu Sep 1 13:02:42 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Thu Sep 1 12:56:20 2005 Subject: [suby-talk] Truly Private Methods In-Reply-To: <4b6f054f05090108327df0438f@mail.gmail.com> References: <4b6f054f0508251014524bdf9a@mail.gmail.com> <4b6f054f05082603576022fb11@mail.gmail.com> <4b6f054f05082714374698bf3b@mail.gmail.com> <4b6f054f050829074423c6c3c7@mail.gmail.com> <4b6f054f0508300807f6eff01@mail.gmail.com> <4b6f054f05090108327df0438f@mail.gmail.com> Message-ID: On Thu, 1 Sep 2005, TRANS wrote: > Thinking about your namespace idea and had a thought. Presently one > can define a "meta" method: > > class X > def self.x ; ... ; end > end > > Or as singleton on an object. > > o = Object.new > def o.x ; ... ; end > > I wonder if it can be extended to autovivify to a namspace if an > object of that name doesn't exist? > > class X > def o.x ; ... ; end > end Your example is a pretty bad one I guess because it creates a new object, defines a method for it, and leaves the object for the GC to snack on. But I do think this would be possible, sure enough, although I don't see a clear link with namespaces, but I think that may be because we both may still have a different idea about them. > Also, does that mean a namespace is a class? > > class Namespace > initialize( obj ) > self = obj # not possible but if > end > end Sure, there could be a Namespace class. Though maybe as with binding, instantiation can't be done explicitly. I'll have to think of that. But I'm not sure what the initialize above would do. Maybe I should put my ideas on namespaces on the wiki, see where it gets me, and see what you think about it. It seems to me that we are on a slightly different wavelength for the moment. Sometimes you go a bit faster than I can follow... Peter From transfire at gmail.com Thu Sep 1 15:36:44 2005 From: transfire at gmail.com (TRANS) Date: Thu Sep 1 15:29:56 2005 Subject: [suby-talk] Truly Private Methods In-Reply-To: References: <4b6f054f0508251014524bdf9a@mail.gmail.com> <4b6f054f05082714374698bf3b@mail.gmail.com> <4b6f054f050829074423c6c3c7@mail.gmail.com> <4b6f054f0508300807f6eff01@mail.gmail.com> <4b6f054f05090108327df0438f@mail.gmail.com> Message-ID: <4b6f054f050901123673e5e4f2@mail.gmail.com> On 9/1/05, Peter Vanbroekhoven wrote: > On Thu, 1 Sep 2005, TRANS wrote: > > > Thinking about your namespace idea and had a thought. Presently one > > can define a "meta" method: > > > > class X > > def self.x ; ... ; end > > end > > > > Or as singleton on an object. > > > > o = Object.new > > def o.x ; ... ; end > > > > I wonder if it can be extended to autovivify to a namspace if an > > object of that name doesn't exist? > > > > class X > > def o.x ; ... ; end > > end > > Your example is a pretty bad one I guess because it creates a new object, > defines a method for it, and leaves the object for the GC to snack on. That don't sound so good :-( I didn't think it would leave the object though, but I suppose(d) it would loose the reference to it after the class closes. > But I do think this would be possible, sure enough, although I don't see a > clear link with namespaces, but I think that may be because we both may > still have a different idea about them. > > > Also, does that mean a namespace is a class? > > > > class Namespace > > initialize( obj ) > > self = obj # not possible but if > > end > > end > > Sure, there could be a Namespace class. Though maybe as with binding, > instantiation can't be done explicitly. I'll have to think of that. > > But I'm not sure what the initialize above would do. > > Maybe I should put my ideas on namespaces on the wiki, see where it gets > me, and see what you think about it. It seems to me that we are on a > slightly different wavelength for the moment. Sometimes you go a bit > faster than I can follow... Sorry, more then likely I'm just confused. But you're right, I get a head of myself even. It would be very great/helpful to see your ideas about this on the wiki. So, to slow down and clarify... I was thinking about your concept of private and protected _named_ namespaces. I believe you wrote: private:foo() Where private was an explictly named namespace and foo of course the method in it. Recall I was thinking about how classes/modules form a kind of namespace and I created that example of using classes to provide these private/protected namespaces. I was further thinking about the metaclass/singleton-class in the same manner, and thought of the shorthand used to define methods in their scope (def self.foo). So I extrapolated from this to: class X ns = Namespace.new( self ) def ns.ameth ... And then thought perhaps the ns could be autovivified. Anyway, that was basically my train of thought. But probably I'm not understanding something significant about namespaces --I get the feeling I missing something. I just don't know what it is, so I don't know how to ask about it :-( T. From calamitas at advalvas.be Fri Sep 2 18:40:42 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Fri Sep 2 18:34:19 2005 Subject: [suby-talk] Truly Private Methods In-Reply-To: <4b6f054f050901123673e5e4f2@mail.gmail.com> References: <4b6f054f0508251014524bdf9a@mail.gmail.com> <4b6f054f05082714374698bf3b@mail.gmail.com> <4b6f054f050829074423c6c3c7@mail.gmail.com> <4b6f054f0508300807f6eff01@mail.gmail.com> <4b6f054f05090108327df0438f@mail.gmail.com> <4b6f054f050901123673e5e4f2@mail.gmail.com> Message-ID: On Thu, 1 Sep 2005, TRANS wrote: > Sorry, more then likely I'm just confused. But you're right, I get a > head of myself even. It would be very great/helpful to see your ideas > about this on the wiki. I will do so. > So, to slow down and clarify... I was thinking about your concept of > private and protected _named_ namespaces. I believe you wrote: > > private:foo() > > Where private was an explictly named namespace and foo of course the > method in it. Recall I was thinking about how classes/modules form a > kind of namespace and I created that example of using classes to > provide these private/protected namespaces. I was further thinking > about the metaclass/singleton-class in the same manner, and thought of > the shorthand used to define methods in their scope (def self.foo). So > I extrapolated from this to: > > class X > ns = Namespace.new( self ) > def ns.ameth > ... > > And then thought perhaps the ns could be autovivified. Ah yes, now I understand, and yes, namespaces are autovivified, definitely. But I'm not sure if namespaces should be explicitly controllable as above. I'll have to think about that more. I think I was confused by your notation. I suppose the more or less standard notation for namespaces would be like this: class X def ns:ameth end end I know that conflicts with the idea of method tags, but maybe that's something we will have to accept, unless we can come up with another notation. Maybe your notation could work, but it may give some useability problems. Anyway, in the example above, the ns namespace would be created if it didn't exist yet, that's one thing I can say for sure. > Anyway, that was basically my train of thought. But probably I'm not > understanding something significant about namespaces --I get the > feeling I missing something. I just don't know what it is, so I don't > know how to ask about it :-( Maybe we should put the discussion about namespaces on hold until I've dumped my ideas on the wiki. Peter From transfire at gmail.com Thu Sep 8 20:57:31 2005 From: transfire at gmail.com (TRANS) Date: Thu Sep 8 20:50:30 2005 Subject: [suby-talk] meta and attr Message-ID: <4b6f054f0509081757360f1978@mail.gmail.com> For awhile I had worrying about what to name some convenience methods for creating class attributes: def class_attr(*arg) (class << self; self; end).class_eval { attr(*args) } end I thought class_attr was okay, but kind of long. I couldn't use cattr b/c DHH already cooped it for creating class variable attributes. At one point meta_attr came across my mind, when it hit me: class Object def meta class< Interesting idea for Nemerle language. Partial application on steroids. In ML you could apply two argument function to a single argument and get another single argument function. We now support a similar, yet more powerful, feature: some_fun (e1, _, e2, _) is transformed to fun (x, y) { some_fun (e1, x, e2, y) } Partial application can be therefore written as 'f (x, _)'. It also works for member access: _.foo will be rewritten to: fun (x) { x.foo } T. From transfire at gmail.com Wed Sep 14 11:59:01 2005 From: transfire at gmail.com (TRANS) Date: Wed Sep 14 11:51:47 2005 Subject: [suby-talk] Re: Partial application In-Reply-To: <4b6f054f05091408492e7d0398@mail.gmail.com> References: <4b6f054f05091408492e7d0398@mail.gmail.com> Message-ID: <4b6f054f05091408591d3b4aa7@mail.gmail.com> In fact this page demonstrates a few other interesting features. http://nemerle.org/Features Check out the macros. T. From calamitas at advalvas.be Thu Sep 15 12:04:49 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Thu, 15 Sep 2005 18:04:49 +0200 (CEST) Subject: [suby-talk] Partial application In-Reply-To: <4b6f054f05091408492e7d0398@mail.gmail.com> References: <4b6f054f05091408492e7d0398@mail.gmail.com> Message-ID: On Wed, 14 Sep 2005, TRANS wrote: > Interesting idea for Nemerle language. > > Partial application on steroids. In ML you could apply two argument > function to a single argument and get another single argument > function. We now support a similar, yet more powerful, feature: > some_fun (e1, _, e2, _) > is transformed to > fun (x, y) { some_fun (e1, x, e2, y) } > Partial application can be therefore written as 'f (x, _)'. It also > works for member access: > _.foo > will be rewritten to: > fun (x) { x.foo } Oh, this is very nice. I've thought about this before, but this is a much better syntax than anything I've been able to come up with. BTW, would you be happy with currying in Ruby if it was restricted to something like above? The problem with currying in Ruby is that you often need to indicate that that is what you want to do. Ruby can detect that you want currying when you supply fewer arguments than required. But that can mask errors and delay them until some possibly unrelated point in the code. In other cases (splat operator, default values) Ruby needs to do a guess, and the only one that makes sense is not to curry (otherwise default values no longer work). Of course in Ruby _ can't really be used as above because it is a valid variable name that is actually used by irb to store the value of the last expression that was evaluated. Maybe we can use a dot. So currying would look like this: meth(a, ., ., 5) with possible shorthands like this: meth(a, .., 5) For the usual kind of currying, that could look like: meth(a, ...) Or just two dots, that doesn't matter. It just means that one or more dot at the end indicates zero or more extra arguments. Peter From transfire at gmail.com Tue Sep 20 10:24:08 2005 From: transfire at gmail.com (TRANS) Date: Tue, 20 Sep 2005 10:24:08 -0400 Subject: [suby-talk] Meta programming from without Message-ID: <4b6f054f050920072432ff14@mail.gmail.com> This morning I was thinking again about meta-programming. I don't know if you've read my latest blog entry. In it I talk about whether meta-programming methods would be better if they acted from without instead of within the object. For instance: "string".is_a?(String) or String === "string" vs. MP::is?(String, "string") T. From calamitas at advalvas.be Tue Sep 20 20:45:44 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Wed, 21 Sep 2005 02:45:44 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f050920072432ff14@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> Message-ID: On Tue, 20 Sep 2005, TRANS wrote: > This morning I was thinking again about meta-programming. I don't know > if you've read my latest blog entry. In it I talk about whether > meta-programming methods would be better if they acted from without > instead of within the object. For instance: > > "string".is_a?(String) > > or > > String === "string" > > vs. > > MP::is?(String, "string") Well, I guess the arguments against are as follows: * It's less OO-ey. * Because of that, overriding the behavior of is_a? in the second case would mean adding a layer over MP::is? (with aliasing, or cuts, or other tricks), which seems rather awkward. * These extra layers would slow things down. It seems to me though that you only want to do this for methods that should not be overridden. I'm not sure that === is among them as it does general matching, not just for classes. OTOH I understand your reason to do it, namely to keep Object as clean as possible method-wise. Well, that's what I understood from it --correct me if I'm wrong. I'm just not sure if that's reason enough to change this. It goes against everything I've learned about OO design. As usual, I suspect I must be misunderstanding the point... Peter From transfire at gmail.com Tue Sep 20 22:10:59 2005 From: transfire at gmail.com (TRANS) Date: Tue, 20 Sep 2005 22:10:59 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> Message-ID: <4b6f054f05092019105c2fa613@mail.gmail.com> Let me know if the return address problem is fixed. Thanks. On 9/20/05, Peter Vanbroekhoven wrote: > > Well, I guess the arguments against are as follows: > * It's less OO-ey. Or more, in the sense of being strict about good OOP practice. > * Because of that, overriding the behavior of is_a? in the second case > would mean adding a layer over MP::is? (with aliasing, or cuts, or other > tricks), which seems rather awkward. These methods one generally does not want to override --that would entail some very extreme meta-programming. > * These extra layers would slow things down. That always a problem, isn't it? :-/ > It seems to me though that you only want to do this for methods that > should not be overridden. I'm not sure that === is among them as it does > general matching, not just for classes. That's true. #=== would still remain, and perhaps for classes route it through the MP (or whatever it would be called). But yes, the idea is that there are methods that one wants to keep "safe" as a matter of meta-programming. Currently the (minimal) convention is to provide __ameth__ methods. But these give no guarantee, and some methods aren't provided for (__class__ for instance). In other cases #instance_ameth is used. Then there are the few others --a new example, Matz is now thinking of adding #fcall. > OTOH I understand your reason to do it, namely to keep Object as clean as > possible method-wise. Well, that's what I understood from it --correct me > if I'm wrong. Keeping it clean is a nice side-effect. But the main reason is two fold. 1) ensure the availability of meta-programming features. Currently they are rather scattered about name-wise and can be too easily overridden, even inadvertently. And 2) to keep with good OOP practices. One of the reasons Matz uses long method names like #instance_variable_get is simply to discourage usage b/c it is not good OOP. I've always felt this approach bordering on silly. T. From calamitas at advalvas.be Wed Sep 21 08:58:13 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Wed, 21 Sep 2005 14:58:13 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f05092019105c2fa613@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> Message-ID: On Tue, 20 Sep 2005, TRANS wrote: > Let me know if the return address problem is fixed. Thanks. Sure is. Thanks. > On 9/20/05, Peter Vanbroekhoven wrote: >> >> Well, I guess the arguments against are as follows: >> * It's less OO-ey. > > Or more, in the sense of being strict about good OOP practice. Could you explain that? Maybe I'm misunderstanding you, but I've always learned that is is bad to centralize a method whose behavior varies with the class of one of its arguments. This is the case with === as what it does differs for say classes and regexps, such that the centralized method needs to check the class of what used to be the receiver. I know === is a bad example, but something likewise is true for the instance_xxx methods, as they only work for classes and thus the centralized method needs to do that class check. Even for languages like Java, explicit class checks are seriously frowned upon. Of course it would be okay designwise to have Inspect.instance_xxx(obj) call obj.instance_xxx to handle the polymorphism, but then I wonder who would use Inspect.instance_xxx(obj). >> * Because of that, overriding the behavior of is_a? in the second case >> would mean adding a layer over MP::is? (with aliasing, or cuts, or other >> tricks), which seems rather awkward. > > These methods one generally does not want to override --that would > entail some very extreme meta-programming. Well, I don't know. Say I have a proxy object (for a remote object say). Then I would want to override class, clone, eval, var_get, var_set and so on to work on the proxied object, or in other words I would want to override these methods. So for example class would need to create a proxy for the proxied object's class. That's far from far-fetched. >> * These extra layers would slow things down. > > That always a problem, isn't it? :-/ Well, in this case the solution would be to use polymorphism. That's what it is there for, isn't it? >> It seems to me though that you only want to do this for methods that >> should not be overridden. I'm not sure that === is among them as it does >> general matching, not just for classes. > > That's true. #=== would still remain, and perhaps for classes route it > through the MP (or whatever it would be called). But think about this. klass === obj would call MP#is?(klass, obj) which then checks that klass is actually a class and then does whatever klass === obj does now. That seems all wrong to me. > But yes, the idea is that there are methods that one wants to keep > "safe" as a matter of meta-programming. Currently the (minimal) > convention is to provide __ameth__ methods. But these give no > guarantee, and some methods aren't provided for (__class__ for > instance). In other cases #instance_ameth is used. Then there are the > few others --a new example, Matz is now thinking of adding #fcall. Then why not provide __methods__ for all these meta-methods? > Keeping it clean is a nice side-effect. But the main reason is two > fold. 1) ensure the availability of meta-programming features. > Currently they are rather scattered about name-wise and can be too > easily overridden, even inadvertently. And 2) to keep with good OOP > practices. One of the reasons Matz uses long method names like > #instance_variable_get is simply to discourage usage b/c it is not > good OOP. I've always felt this approach bordering on silly. As to your first reason, would it make sense to put these methods inside their own namespace that can be accessed regardless of whether they are overridden or not? As for your second point, I still don't understand why it's better OOP practice. Is it about putting all meta-programming methods together in one place? I agree though that these names are unnecessarily long. OTOH that makes it harder to inadverntently override them ;-) Peter From transfire at gmail.com Wed Sep 21 17:55:15 2005 From: transfire at gmail.com (TRANS) Date: Wed, 21 Sep 2005 17:55:15 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> Message-ID: <4b6f054f050921145555f76ead@mail.gmail.com> On 9/21/05, Peter Vanbroekhoven wrote: > > Or more, in the sense of being strict about good OOP practice. > > Could you explain that? Sure. I'm just talking about things like #instance_variable_get and _set, which allow one to muck about with an object instance vars. Good OOP of course is all about providing proper accessors/mutators. Hence, this kind of thing is meta-programming. Currently #send is another example in that it bypasses public/private/protected protections. And of course instance_eval. These are the methods that skirt some measure of "good" OOP practice. Then there are the other methods that provide language info like class or id. These come into play here with regard to being overridden, thus the meta-programmer can't be perfectly certain of them. > Maybe I'm misunderstanding you, but I've always learned that is is bad to > centralize a method whose behavior varies with the class of one of its > arguments. This is the case with === as what it does differs for say > classes and regexps, such that the centralized method needs to check the > class of what used to be the receiver. I know === is a bad example, but > something likewise is true for the instance_xxx methods, as they only work > for classes and thus the centralized method needs to do that class check. > Even for languages like Java, explicit class checks are seriously frowned > upon. Of course it would be okay designwise to have > Inspect.instance_xxx(obj) call obj.instance_xxx to handle the > polymorphism, but then I wonder who would use Inspect.instance_xxx(obj). > > >> * Because of that, overriding the behavior of is_a? in the second case > >> would mean adding a layer over MP::is? (with aliasing, or cuts, or other > >> tricks), which seems rather awkward. > > > > These methods one generally does not want to override --that would > > entail some very extreme meta-programming. > > Well, I don't know. Say I have a proxy object (for a remote object say). > Then I would want to override class, clone, eval, var_get, var_set and so > on to work on the proxied object, or in other words I would want to > override these methods. So for example class would need to create a proxy > for the proxied object's class. That's far from far-fetched. Right. Proxies are actually exactly the thing I'm thinking about. If the proxy overrides all those methods how does one get a hold of the Proxy itself? One would not be able to. So we end using some convention of reserving certian methods to NOT be overriden, but there is no standard to this and currently is completely haphazard. For exmaple, presently I use a BlankSlate class as a basis for kinds of Proxies: require 'nano/object/__self__' require 'nano/object/__class__' require 'nano/object/__clone__' require 'nano/object/__dup__' class BlankSlate EXCLUDE = %w{ __ instance_ inspect respond_to? is_a? kind_of? } class << self def hide(name) if instance_methods.include?(name.to_s) and name !~ /^(#{EXCLUDE.join('|')})/ undef_method name end end end instance_methods.each { |m| hide(m) } end It works okay, but it's just my personal convention. No one can rely on it being this way for other's people stuff. Nor am I sure its good enough --if I've missied something important, etc. > But think about this. klass === obj would call MP#is?(klass, obj) which > then checks that klass is actually a class and then does whatever klass > === obj does now. That seems all wrong to me. Isn't "checks that klass is actually a class" the same as "whatever klass === obj does now"? I understand it has a differnt use for other objects, but for a class #=== essenitially does what MP#is?(klass, obj) does. It's C code under the hood after all. I'm not saying it needs to call MP, just that it could. But even for a class #=== can be overriden to do something else, and thus has no insurance to check class. Doing certain meta-programming I need the insurance. How do I get it? > > But yes, the idea is that there are methods that one wants to keep > > "safe" as a matter of meta-programming. Currently the (minimal) > > convention is to provide __ameth__ methods. But these give no > > guarantee, and some methods aren't provided for (__class__ for > > instance). In other cases #instance_ameth is used. Then there are the > > few others --a new example, Matz is now thinking of adding #fcall. > > Then why not provide __methods__ for all these meta-methods? Well that's one solution (though all those __ do get might ugly) > > Keeping it clean is a nice side-effect. But the main reason is two > > fold. 1) ensure the availability of meta-programming features. > > Currently they are rather scattered about name-wise and can be too > > easily overridden, even inadvertently. And 2) to keep with good OOP > > practices. One of the reasons Matz uses long method names like > > #instance_variable_get is simply to discourage usage b/c it is not > > good OOP. I've always felt this approach bordering on silly. > > As to your first reason, would it make sense to put these methods inside > their own namespace that can be accessed regardless of whether they are > overridden or not? Well, I think so. I think that's mainly what I'm trying to achieve by having an external meta function module --if I understand you correctly. The only reason I'm inclined to think that it might be better for such methods to exist outside the object is b/c they are generally doing "overt" things to the object, "meta" things, and there's no interference with the rest of the object. But it's not strictly essential, as long as they are somehow protected and minimize interference with the rest of the object, say with only one point of reference, (eg. object.meta.ametamethod), I think that would be reasonble. > I agree though that these names are unnecessarily long. OTOH that makes it > harder to inadverntently override them ;-) Ah, so the longer the name the closer to my insurance! Lay on the verbosity baby! ;-) T. From transfire at gmail.com Wed Sep 21 20:32:17 2005 From: transfire at gmail.com (TRANS) Date: Wed, 21 Sep 2005 20:32:17 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> Message-ID: <4b6f054f0509211732a7f09f2@mail.gmail.com> On 9/20/05, Peter Vanbroekhoven wrote: > As usual, I suspect I must be misunderstanding the point... As usual, I suspect I did not explian the point well enough... T. P.S. Hope 1.8.3 isn't too difficult to port over. How do you go about it actually? From calamitas at advalvas.be Fri Sep 23 15:11:34 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Fri, 23 Sep 2005 21:11:34 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f050921145555f76ead@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> Message-ID: On Wed, 21 Sep 2005, TRANS wrote: > Sure. I'm just talking about things like #instance_variable_get and > _set, which allow one to muck about with an object instance vars. Good > OOP of course is all about providing proper accessors/mutators. Hence, > this kind of thing is meta-programming. Currently #send is another > example in that it bypasses public/private/protected protections. And > of course instance_eval. These are the methods that skirt some measure > of "good" OOP practice. Ah, I see. But moving all of these methods to a completely separate class or module does not change the nature of these methods. Despite the fact that what they do is not very good OOP practice, OOP still dictates that they belong in the class of the object they operate on. > Then there are the other methods that provide language info like class > or id. These come into play here with regard to being overridden, thus > the meta-programmer can't be perfectly certain of them. Well, it's Ruby. You can never be perfectly certain of anything. But I think I understand your concern. I remember one particular case where I was overriding #hash in a subclass of one of the builtin classes, possibly Array. I needed the original #hash method, but because Array overrides it, it's impossible to get to that method except by using a combination of Module#instance_method and UnboundMethod#bind, which is way too wordy. > Right. Proxies are actually exactly the thing I'm thinking about. If > the proxy overrides all those methods how does one get a hold of the > Proxy itself? One would not be able to. So we end using some > convention of reserving certian methods to NOT be overriden, but there > is no standard to this and currently is completely haphazard. For > exmaple, presently I use a BlankSlate class as a basis for kinds of > Proxies: Well, I suppose the question is whether one should be able to get hold of the proxy. In a way I suppose that breaks encapsulation. The proxy can then only be accessed from within the proxy, which would be perfect encapsulation. That's not always what you want, of course. > It works okay, but it's just my personal convention. No one can rely > on it being this way for other's people stuff. Nor am I sure its good > enough --if I've missied something important, etc. Maybe you should establish a new convention then! Someone has to do that; can just as well be you. > Isn't "checks that klass is actually a class" the same as "whatever > klass === obj does now"? I understand it has a differnt use for other > objects, but for a class #=== essenitially does what MP#is?(klass, > obj) does. It's C code under the hood after all. I'm not saying it > needs to call MP, just that it could. But even for a class #=== can be > overriden to do something else, and thus has no insurance to check > class. Doing certain meta-programming I need the insurance. How do I > get it? It's not the same. MP#is?(klass, obj) would look like this: def MP.is?(klass, obj) raise TypeError, "#{klass} is not a class" if not Module === klass klass === obj end And you are right, it is hidden in C code. But does that matter? If someone wants to override this method in Ruby, it would be ugly again. And as to insurance, I'm not sure you can get it. Of course you could freeze that MP above, if the evil guys didn't beat you to it. But that wouldn't keep people from reassigning MP altogether, which I guess you can only prevent by freezing Object. Again, if you get to do that before the evil has happened. And if you can live with Object being frozen (well, it ought to seriously cripple Ruby as new toplevel constants couldn't be defined anymore.) And I'm not sure Ruby should offer insurance. Offering one programmer insurance is stealing another guy's freedom. What if someone actually wants to override one of these methods? Of course you could say that MP contains the original version that should not be overridden, and the ones in Object and Module and so on can be overridden. But that doesn't solve a thing, because at some point someone will want to override the methods in MP too. I mean, think of it; you write your code using the methods in MP. Now someone wants to customize your code by overriding the methods in MP, because the ones in Object and Module are useless for that purpose. What putting these methods in MP does accomplish is a higher degree of certainty. But still, if people are aware of these methods, they'll redefine them unless explicitly forbidden in which case they'll even get a kick out of redefining them. I do understand your motivation now though. You want to be sure that when you call one of these meta-methods, it does exactly what you want it to do. It's a frightening world out there, full of people wanting to redefine methods. But just like in the real world where you check under your bed for monsters, you write unit tests to see if everything does what it's supposed to do. > Well that's one solution (though all those __ do get might ugly) Agreed. > Well, I think so. I think that's mainly what I'm trying to achieve by > having an external meta function module --if I understand you > correctly. The only reason I'm inclined to think that it might be > better for such methods to exist outside the object is b/c they are > generally doing "overt" things to the object, "meta" things, and > there's no interference with the rest of the object. But it's not > strictly essential, as long as they are somehow protected and minimize > interference with the rest of the object, say with only one point of > reference, (eg. object.meta.ametamethod), I think that would be > reasonble. How about a namespace which is frozen. One that can always be accessed. I don't intend namespaces to be assigned to constants like mocules and classes are, so they should be undeletable. Access would then be (given that the nanespace is called 'meta' as per your example): object.meta:ametamethod > Ah, so the longer the name the closer to my insurance! Lay on the > verbosity baby! ;-) How about: object.get_object_identifier_that_is_uique_and_should_not_be_overridden That should keep people from accidentally overriding it! Peter From calamitas at advalvas.be Fri Sep 23 15:25:09 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Fri, 23 Sep 2005 21:25:09 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f0509211732a7f09f2@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f0509211732a7f09f2@mail.gmail.com> Message-ID: On Wed, 21 Sep 2005, TRANS wrote: > As usual, I suspect I did not explian the point well enough... Or you going too fast for me. > P.S. Hope 1.8.3 isn't too difficult to port over. How do you go about > it actually? Honestly? I have no idea. But maybe we should consider our versioning first. We kind of have two orthogonal versions to worry about. There's the version of Suby itself, but there's also the version of Ruby it is based on. So how do we do this? Do we employ a dual versioning scheme, maybe something like this: Suby 0.1/1.8.3 Of course in this case we don't have Suby 0.1 yet, and the version of Ruby it is based on is 1.8.3 preview 1. So that could then be: Suby 0.1 preview 0/1.8.3 preview 1 Well, what do you think? (Please note the irony in the right places; people say they don't always know when I'm being ironic or sarcastic.) Peter From transfire at gmail.com Fri Sep 23 16:49:15 2005 From: transfire at gmail.com (TRANS) Date: Fri, 23 Sep 2005 16:49:15 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> Message-ID: <4b6f054f05092313491040ce3@mail.gmail.com> On 9/23/05, Peter Vanbroekhoven wrote: > Ah, I see. But moving all of these methods to a completely separate class > or module does not change the nature of these methods. Despite the fact > that what they do is not very good OOP practice, OOP still dictates that > they belong in the class of the object they operate on. I guess that's truem, yet I have come to realize OOP can't escape being built on top of a non-OOP infrustructure, and in meta-programming one is basically dealing witht things at that lower level. > Well, it's Ruby. You can never be perfectly certain of anything. But I > think I understand your concern. I remember one particular case where I > was overriding #hash in a subclass of one of the builtin classes, > possibly Array. I needed the original #hash method, but because Array > overrides it, it's impossible to get to that method except by using a > combination of Module#instance_method and UnboundMethod#bind, which is > way too wordy. Right. And even worse, other parts of Ruby or ext. libs might depend on #hash doing what it conventually does. > > It works okay, but it's just my personal convention. No one can rely > > on it being this way for other's people stuff. Nor am I sure its good > > enough --if I've missied something important, etc. > > Maybe you should establish a new convention then! Someone has to do that; > can just as well be you. Good idea! :-) Onely thing is, no one ever listens to me :-( I suppose the safe bet is to stick with __xyz__ methods and expand on those. Right now I'm looking at 4 options: # "shadow" methods @x.__dup__.__send__( @op, obj.x ) # special prefix @x.instance_dup.instance_send( @op, obj.x ) # Special send-like Object module method Object.instance( Object.instance( @x, :dup ), :send, @op, obj.x ) # ObjectSpace module methods ObjectSpace.send( ObjectSpace.dup(@x), @op, obj.x ) > > Isn't "checks that klass is actually a class" the same as "whatever > > klass === obj does now"? I understand it has a differnt use for other > > objects, but for a class #=== essenitially does what MP#is?(klass, > > obj) does. It's C code under the hood after all. I'm not saying it > > needs to call MP, just that it could. But even for a class #=== can be > > overriden to do something else, and thus has no insurance to check > > class. Doing certain meta-programming I need the insurance. How do I > > get it? > > It's not the same. MP#is?(klass, obj) would look like this: > > def MP.is?(klass, obj) > raise TypeError, "#{klass} is not a class" if not Module === klass > klass === obj > end Hmm... I was thinking of it more along the lines that the MP would actually be the internal provisioner of what all these things mean. For example I added: def f?( obj ) return true if is_a?(obj,NilClass) return true if is_a?(obj,FalseClass) return true if defined?(NullClass) and is_a?(obj,NullClass) return true if defined?(NackClass) and is_a?(obj,NackClass) false end So #if itself _could_ call on that. Currently these things are out of reach, in Ruby's core. (Of course, this would indeed slow things down a lot too.) But I suppose you are right, in that it still skirts polymorphism. > And you are right, it is hidden in C code. But does that matter? If > someone wants to override this method in Ruby, it would be ugly again. True. > And as to insurance, I'm not sure you can get it. Of course you could > freeze that MP above, if the evil guys didn't beat you to it. But that > wouldn't keep people from reassigning MP altogether, which I guess you can > only prevent by freezing Object. Again, if you get to do that before the > evil has happened. And if you can live with Object being frozen (well, it > ought to seriously cripple Ruby as new toplevel constants couldn't be > defined anymore.) Get'n cold in here ;-) > And I'm not sure Ruby should offer insurance. Offering one programmer > insurance is stealing another guy's freedom. What if someone actually > wants to override one of these methods? Of course you could say that MP > contains the original version that should not be overridden, and the ones > in Object and Module and so on can be overridden. But that doesn't solve a > thing, because at some point someone will want to override the methods in > MP too. I mean, think of it; you write your code using the methods in MP. > Now someone wants to customize your code by overriding the methods in MP, > because the ones in Object and Module are useless for that purpose. What > putting these methods in MP does accomplish is a higher degree of > certainty. But still, if people are aware of these methods, they'll > redefine them unless explicitly forbidden in which case they'll even get a > kick out of redefining them. Right. I don't want to stop overriding all together. I'm just think along the lines of having a standard route to get this info --so even if one were overriding it, it would be to add something in the same regard; not something wholly different. Case in point I'd like to open up objects to be used as essentially perfect OpenStruct containers. Currenlty many methods get in the way. I use BlankSlate to get rid of most of them and alias others (ie. __xyz__). But not all of them can be gotten rid of b/c too much depends on them --and the more you do the less likely other stuff will work with it. > I do understand your motivation now though. You want to be sure that when > you call one of these meta-methods, it does exactly what you want it to > do. It's a frightening world out there, full of people wanting to redefine > methods. But just like in the real world where you check under your bed > for monsters, you write unit tests to see if everything does what it's > supposed to do. Yes, that's true. But also I can't test my stuff with a lib that doesn't exist yet either. In other words, I want my stuff to work with other people are doing/planning as well. > > Well that's one solution (though all those __ do get might ugly) > > Agreed. > > How about a namespace which is frozen. One that can always be accessed. I > don't intend namespaces to be assigned to constants like mocules and > classes are, so they should be undeletable. Access would then be (given > that the nanespace is called 'meta' as per your example): > > object.meta:ametamethod Likely the best solution, at least in the long run. And I don't know if it even has to be frozen either. Just so long as it's useage is standardized --people won't mess with it --won't have to, unless they are doing something very special. > > Ah, so the longer the name the closer to my insurance! Lay on the > > verbosity baby! ;-) > > How about: > > object.get_object_identifier_that_is_uique_and_should_not_be_overridden > > That should keep people from accidentally overriding it! LOL! I'm feel'n safe, but my screen's running out of space and my fingers hurt :-) T. From transfire at gmail.com Fri Sep 23 16:57:26 2005 From: transfire at gmail.com (TRANS) Date: Fri, 23 Sep 2005 16:57:26 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f0509211732a7f09f2@mail.gmail.com> Message-ID: <4b6f054f050923135711c65fe6@mail.gmail.com> On 9/23/05, Peter Vanbroekhoven wrote: > On Wed, 21 Sep 2005, TRANS wrote: > > > As usual, I suspect I did not explian the point well enough... > > Or you going too fast for me. > > > P.S. Hope 1.8.3 isn't too difficult to port over. How do you go about > > it actually? > > Honestly? I have no idea. > > But maybe we should consider our versioning first. We kind of have two > orthogonal versions to worry about. There's the version of Suby itself, > but there's also the version of Ruby it is based on. So how do we do this? > Do we employ a dual versioning scheme, maybe something like this: > > Suby 0.1/1.8.3 That seems good. (I wouldn't even worry about preview number) > Of course in this case we don't have Suby 0.1 yet, and the version of Ruby > it is based on is 1.8.3 preview 1. So that could then be: > > Suby 0.1 preview 0/1.8.3 preview 1 > > Well, what do you think? (Please note the irony in the right places; > people say they don't always know when I'm being ironic or sarcastic.) Hey, where can I get a copy of Preview 0? ;-) (Of course this is ironic, b/c people say I stink at detecting subtle irony and satire.) T. From calamitas at advalvas.be Fri Sep 23 19:04:36 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sat, 24 Sep 2005 01:04:36 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f05092313491040ce3@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> Message-ID: On Fri, 23 Sep 2005, TRANS wrote: > I guess that's truem, yet I have come to realize OOP can't escape > being built on top of a non-OOP infrustructure, and in > meta-programming one is basically dealing witht things at that lower > level. Still, I'd rather write obj.object_id then Inspect.object_id(obj). It's a bit backwards. If I want to use the object's id, I need to add things on both sides of obj. It starts to feel more like C or Java. Actually it's worse than C. > Right. And even worse, other parts of Ruby or ext. libs might depend > on #hash doing what it conventually does. Extensions can refer to the original implementation at all times, as follows: rb_obj_id(obj) Guaranteed to always return the original object id, which also happens to be the hash value of an object (there's just one function internally, though in Ruby they are separate). > Good idea! :-) Onely thing is, no one ever listens to me :-( I suppose > the safe bet is to stick with __xyz__ methods and expand on those. > Right now I'm looking at 4 options: > > # "shadow" methods > @x.__dup__.__send__( @op, obj.x ) > > # special prefix > @x.instance_dup.instance_send( @op, obj.x ) > > # Special send-like Object module method > Object.instance( Object.instance( @x, :dup ), :send, @op, obj.x ) > > # ObjectSpace module methods > ObjectSpace.send( ObjectSpace.dup(@x), @op, obj.x ) You know, Object#id would somehow be OK as ObjectSpace#id or ObjectSpace#id_of, but #send and #dup seem wrong there. That doesn't mean ObjectSpace#id_of wouldn't be awkward. > Hmm... I was thinking of it more along the lines that the MP would > actually be the internal provisioner of what all these things mean. > For example I added: > > def f?( obj ) > return true if is_a?(obj,NilClass) > return true if is_a?(obj,FalseClass) > return true if defined?(NullClass) and is_a?(obj,NullClass) > return true if defined?(NackClass) and is_a?(obj,NackClass) > false > end > > So #if itself _could_ call on that. Currently these things are out of > reach, in Ruby's core. (Of course, this would indeed slow things down > a lot too.) But I suppose you are right, in that it still skirts > polymorphism. That's the point indeed. > Right. I don't want to stop overriding all together. I'm just think > along the lines of having a standard route to get this info --so even > if one were overriding it, it would be to add something in the same > regard; not something wholly different. Case in point I'd like to open > up objects to be used as essentially perfect OpenStruct containers. > Currenlty many methods get in the way. I use BlankSlate to get rid of > most of them and alias others (ie. __xyz__). But not all of them can > be gotten rid of b/c too much depends on them --and the more you do > the less likely other stuff will work with it. With OpenStruct I can see the problem, yes. Things like id and class are not really that far-fetched as field names. But I just thought of an old idea of me that would go in one of those languages I started writing once. It was about roles. It's inspired by real life. In real life people play different roles. So maybe we need to have this concept for object too. For example an OpenStruct object could have two roles, that of a structure with fields, and that of an meta-programmable object. Or a Proxy could take the role of the proxied object, or that of the proxy itself. Say the role of the proxied object is the standard role. Then if you need to manipulate it as the proxy, you could do something like this: (obj as :proxy).do_something I don't know about the syntax, like this it will almost always require brackets, but it should give you the idea. This idea came from a statically typed language, so it was not really a problem that the object seems to temporarily change class or so. In Ruby it needs to return a new object, which will incur a certain overhead. Well, unless the roles are cached of course, but it needs to be done for each object. This 'as' thing can be a keyword, totally meta which no one can override. I think I may even be able to cook up an implementation of this pretty easily. > Yes, that's true. But also I can't test my stuff with a lib that > doesn't exist yet either. In other words, I want my stuff to work with > other people are doing/planning as well. I know. I think that's a more general problem in Ruby than what we are discussing here. I mean, it is a problem for libraries, not so much for applications that use the libraries as they come whining to the library maintainers. > Likely the best solution, at least in the long run. And I don't know > if it even has to be frozen either. Just so long as it's useage is > standardized --people won't mess with it --won't have to, unless they > are doing something very special. Agreed. But I understand the problem better now. I think what bothers me most about the solution of putting all these methods in a separate module is that the flow of the program starts to go backwards. The method call comes before the object it operates on. It goes against the thinking process. Subconciously, it frightens people. Or at least me. I think this flow thing is one of the things that attracts people to Ruby. But besides that I see two solutions: namespaces, and roles. Both are interesting concepts IMO. > LOL! I'm feel'n safe, but my screen's running out of space and my > fingers hurt :-) Ah yes, that's why Java people need IDE's with auto-completion! Has its advantaged though ;-) Peter From transfire at gmail.com Fri Sep 23 23:55:23 2005 From: transfire at gmail.com (TRANS) Date: Fri, 23 Sep 2005 23:55:23 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> Message-ID: <4b6f054f050923205527c12645@mail.gmail.com> On 9/23/05, Peter Vanbroekhoven wrote: > Still, I'd rather write obj.object_id then Inspect.object_id(obj). It's a > bit backwards. If I want to use the object's id, I need to add things on > both sides of obj. It starts to feel more like C or Java. Actually it's > worse than C. I agreed. > Extensions can refer to the original implementation at all times, as > follows: > > rb_obj_id(obj) > > Guaranteed to always return the original object id, which also happens to > be the hash value of an object (there's just one function internally, > though in Ruby they are separate). Ah, see I can't get that in Ruby itself. Maybe adding something like that to ObjectSpace is a good idea then. I was exploring the shadow method idea, ie. __xyz__, that has it's advantages w/ polymorphism as such, but it just seems crazy to have all those __methods__. I don't know. Another idea born of this and and a though on another one of out disscusions: @x.__(:dup).__(:send, @op, obj.x ) > But I just thought of an old idea of me that would go in one of those > languages I started writing once. It was about roles. It's inspired by > real life. In real life people play different roles. So maybe we need to > have this concept for object too. For example an OpenStruct object could > have two roles, that of a structure with fields, and that of an > meta-programmable object. Or a Proxy could take the role of the proxied > object, or that of the proxy itself. Say the role of the proxied object is > the standard role. Then if you need to manipulate it as the proxy, you > could do something like this: > > (obj as :proxy).do_something > > I don't know about the syntax, like this it will almost always require > brackets, but it should give you the idea. This idea came from a > statically typed language, so it was not really a problem that the object > seems to temporarily change class or so. In Ruby it needs to return a new > object, which will incur a certain overhead. Well, unless the roles are > cached of course, but it needs to be done for each object. This 'as' thing > can be a keyword, totally meta which no one can override. I think I may > even be able to cook up an implementation of this pretty easily. Wow. I think that is awsome. Actually I think we talked about this briefly once before. Also, this seems very similar to namespaces. I'm not even quite sure how they differ? > I know. I think that's a more general problem in Ruby than what we are > discussing here. I mean, it is a problem for libraries, not so much for > applications that use the libraries as they come whining to the library > maintainers. Indeed. > > Likely the best solution, at least in the long run. And I don't know > > if it even has to be frozen either. Just so long as it's useage is > > standardized --people won't mess with it --won't have to, unless they > > are doing something very special. > > Agreed. But I understand the problem better now. I think what bothers me > most about the solution of putting all these methods in a separate module > is that the flow of the program starts to go backwards. The method call > comes before the object it operates on. It goes against the thinking > process. Subconciously, it frightens people. Or at least me. I think this > flow thing is one of the things that attracts people to Ruby. But besides > that I see two solutions: namespaces, and roles. Both are interesting > concepts IMO. Yes. and something I think we both like to see more of. > > LOL! I'm feel'n safe, but my screen's running out of space and my > > fingers hurt :-) > > Ah yes, that's why Java people need IDE's with auto-completion! Has its > advantaged though ;-) True enough. While I probably wouldn't touch MS Visual Studio again with a 10ft pole, its RAD/IDE features were great. T. From calamitas at advalvas.be Sat Sep 24 14:39:20 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sat, 24 Sep 2005 20:39:20 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f050923205527c12645@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> <4b6f054f050923205527c12645@mail.gmail.com> Message-ID: On Fri, 23 Sep 2005, TRANS wrote: > Ah, see I can't get that in Ruby itself. Maybe adding something like > that to ObjectSpace is a good idea then. > > I was exploring the shadow method idea, ie. __xyz__, that has it's > advantages w/ polymorphism as such, but it just seems crazy to have > all those __methods__. I don't know. Another idea born of this and and > a though on another one of out disscusions: > > @x.__(:dup).__(:send, @op, obj.x ) How about just this: @x.__.dup.__.send(@op, obj.x) Implementation is simply this: class BackToTheBasics def initialize(obj) @self = obj end ['dup', 'send'].each do |m| module_eval %Q{ def #{m}(*args, &blk) Kernel.instance_method(#{m.dump}).bind(@self).call(*args, &blk) end } end end module Kernel def __ @__ ||= BackToTheBasics.new(self) end end > Wow. I think that is awsome. Actually I think we talked about this > briefly once before. Also, this seems very similar to namespaces. I'm > not even quite sure how they differ? Well, it's a different kind of use case. I could do "obj as Proxy" and pass it around to code that will see it as a Proxy. This is irrespective of whatever namespace that code is in, or whatever namespace that code thinks it's seeing. It's a more of a dynamic version of namespaces (namespaces are quite static). > Yes. and something I think we both like to see more of. Oh, definitely! > True enough. While I probably wouldn't touch MS Visual Studio again > with a 10ft pole, its RAD/IDE features were great. The only IDEs I've ever used were Borland Pascal, IntelliJ Idea and Visual Basic. That Visual Basic stuff was over 10 years ago, so it's not what I assume it is now. Peter From transfire at gmail.com Sat Sep 24 15:17:29 2005 From: transfire at gmail.com (TRANS) Date: Sat, 24 Sep 2005 15:17:29 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> <4b6f054f050923205527c12645@mail.gmail.com> Message-ID: <4b6f054f0509241217d57d0b3@mail.gmail.com> On 9/24/05, Peter Vanbroekhoven wrote: > On Fri, 23 Sep 2005, TRANS wrote: > > > Ah, see I can't get that in Ruby itself. Maybe adding something like > > that to ObjectSpace is a good idea then. > > > > I was exploring the shadow method idea, ie. __xyz__, that has it's > > advantages w/ polymorphism as such, but it just seems crazy to have > > all those __methods__. I don't know. Another idea born of this and and > > a though on another one of out disscusions: > > > > @x.__(:dup).__(:send, @op, obj.x ) > > How about just this: > > @x.__.dup.__.send(@op, obj.x) Whoa. almost had me fooled into thinking you managed: @x.__.dup.__ in place of @x.__dup__ :-) > Implementation is simply this: > > class BackToTheBasics > def initialize(obj) > @self = obj > end > ['dup', 'send'].each do |m| > module_eval %Q{ > def #{m}(*args, &blk) > Kernel.instance_method(#{m.dump}).bind(@self).call(*args, &blk) > end > } > end > end > > module Kernel > def __ > @__ ||= BackToTheBasics.new(self) > end > end Nice. That's a very viable solution. Mind if I drop it on Matz to see what he thinks? > > Wow. I think that is awsome. Actually I think we talked about this > > briefly once before. Also, this seems very similar to namespaces. I'm > > not even quite sure how they differ? > > Well, it's a different kind of use case. I could do "obj as Proxy" and > pass it around to code that will see it as a Proxy. This is irrespective > of whatever namespace that code is in, or whatever namespace that code > thinks it's seeing. It's a more of a dynamic version of namespaces > (namespaces are quite static). I think I see. Sort of like attatching the namespace to the object? > > Yes. and something I think we both like to see more of. > > Oh, definitely! Goody goody. > > True enough. While I probably wouldn't touch MS Visual Studio again > > with a 10ft pole, its RAD/IDE features were great. > > The only IDEs I've ever used were Borland Pascal, IntelliJ Idea and Visual > Basic. That Visual Basic stuff was over 10 years ago, so it's not what I > assume it is now. Well, it's been about 6 for me. But you know it has all the nice RAD/IDE stuff. Actually VB has become a rather fair language. MS keeps updating it to take in all the latest OOP stuff --even Ruby inspired ideas. Pluse some interesting addtional like embedded SQL and XML. But being tied to MS: NWIH. BTW to you watch ruby-core mailing list? I posted an idea for close blocks: Class.new [ #... ] If Hash can share it's literal notation, why not array? But there needs to be a way to pass in specific vars. T. From transfire at gmail.com Sat Sep 24 15:46:17 2005 From: transfire at gmail.com (TRANS) Date: Sat, 24 Sep 2005 15:46:17 -0400 Subject: [suby-talk] "Is" and ideas for moving foward Message-ID: <4b6f054f050924124660760250@mail.gmail.com> Today George of Nitro asked me to alias #include to #is: class Foo is Bar end I like it and saw no ready reason now to support it so I added it to Nano. This got me to thinking about how modules are included. I really tire of jumping through hoops using Module#included to tell it I want class method included too. The use of #extend seems backward --why should the class dictate how the module effect it? (except under special circumstances). I think that undermines the whole idea of "enpsulated module". So I propose we get on with it and offer some declarations: module M function def f ; "F" ; end extends def x ; "X" ; end inherits def y ; "Y" ; end end 'function' is the same as current module_function and would be the default. It both acts as a non-extending module function and an instance-level inheritable. So, M.f #=> "F" M.x #=> error M.y #=> error class X is M end X.x #=> "X" X.new.y #=> "Y" X.f #=> error X.new.f #=> "F" (albeit it is private) Also I would like to move foward on ultimately replacing the #methods and #instance_methods to take symbol query parameters, instead of have all the other methods: public_methods, private_methods, etc. In fact if methods tool on more of a 1st class role (even if faked). Then perhaps: M.methods.select { |m| m.access == :private } Of course I still am interesed in throwing out the current private/protected/public for now and start fresh later with a truer form. Finally, I'm curious. And I know this might seem like a shocker. But I often wonder about the fact the #alias doesn't need a comma separated list of arguments. I know it's special but I wonder if it might be generally applicable? class X def intialize( a b c ) #... end end X.new :A :B :C T. From calamitas at advalvas.be Sat Sep 24 15:46:19 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sat, 24 Sep 2005 21:46:19 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f0509241217d57d0b3@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f05092019105c2fa613@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> <4b6f054f050923205527c12645@mail.gmail.com> <4b6f054f0509241217d57d0b3@mail.gmail.com> Message-ID: On Sat, 24 Sep 2005, TRANS wrote: > Whoa. almost had me fooled into thinking you managed: > > @x.__.dup.__ > > in place of > > @x.__dup__ > > :-) Well, I could you know, with a little tweaking. __ wraps @x in a BackToTheBasics object. dup calls the original dup on @x and wraps it again in a BackToTheBasics object. __ on this BackToTheBasics then unwraps it. And then you've got the above! >> Implementation is simply this: >> >> class BackToTheBasics >> def initialize(obj) >> @self = obj >> end >> ['dup', 'send'].each do |m| >> module_eval %Q{ >> def #{m}(*args, &blk) >> Kernel.instance_method(#{m.dump}).bind(@self).call(*args, &blk) >> end >> } >> end >> end >> >> module Kernel >> def __ >> @__ ||= BackToTheBasics.new(self) >> end >> end > > Nice. That's a very viable solution. Mind if I drop it on Matz to see > what he thinks? Please go ahead. >> Well, it's a different kind of use case. I could do "obj as Proxy" and >> pass it around to code that will see it as a Proxy. This is irrespective >> of whatever namespace that code is in, or whatever namespace that code >> thinks it's seeing. It's a more of a dynamic version of namespaces >> (namespaces are quite static). > > I think I see. Sort of like attatching the namespace to the object? Yup, sort of. It's a bit like the BackToTheBasics above: it is wrapped in an object that calls the methods through the namespace it was given at its creation. So the BackToTheBasics thing would just use the Kernel namespace. or whatever we'd call it. >>> Yes. and something I think we both like to see more of. >> >> Oh, definitely! > > Goody goody. :-) > Well, it's been about 6 for me. But you know it has all the nice > RAD/IDE stuff. Actually VB has become a rather fair language. MS keeps > updating it to take in all the latest OOP stuff --even Ruby inspired > ideas. Pluse some interesting addtional like embedded SQL and XML. But > being tied to MS: NWIH. Well, VB back in those days alreayd allowed drawing forms (that's what they called windows, I don't know if they still do that) and drawing buttons on it and then attaching actions to those buttons and all. Yes, it was much fun to play with. I built a mastermind game in it once. And a program that could add/subtract/multiply/divide multiple precision numbers. I reimplemented that in Pascal once to calculate lots of digits of pi. I don't remember how far I got. I think I set up the program to get to a million digits, but due to lack of patience, I decreased that, but I don't remember by how much. Another game I built in VB was a checkers game. But I'm pretty sure these programs don't run anymore on today's Windows systems. It was Windows 3.0 back then. > BTW to you watch ruby-core mailing list? I posted an idea for close blocks: > > Class.new [ > #... > ] > > If Hash can share it's literal notation, why not array? But there > needs to be a way to pass in specific vars. I'm watching ruby-core indeed. Still, the above notation does not convey the idea of closedness to me, so I'm not too keen about it. About passing in variables, and keeping variables in, maybe something like this: Class.new |a, b|[|c, d| # ... ] Well, it's not ideal, but c and d are clearly inside, and a and b clearly come from the outside. Of course it don't jive with Ruby's current block syntax. Combined with that, I think it gets to complicated. Too much punctuation lying around. I don't know, to me it seems that the simple rules of completely closed vs completely open or still best. Part of the problem is that in Ruby variables are not declared. If they were, more combination of openness and closedness would be possible. So maybe local variables need a declaration. For example: Class.new { local a, b } For closed blocks, we need the inverse: Class.new [ global a, b ] I don't know about the word global. Maybe 'escape' or 'escaping' is better. Peter From transfire at gmail.com Sat Sep 24 16:26:05 2005 From: transfire at gmail.com (TRANS) Date: Sat, 24 Sep 2005 16:26:05 -0400 Subject: [suby-talk] Meta programming from without In-Reply-To: References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> <4b6f054f050923205527c12645@mail.gmail.com> <4b6f054f0509241217d57d0b3@mail.gmail.com> Message-ID: <4b6f054f0509241326375e07d1@mail.gmail.com> On 9/24/05, Peter Vanbroekhoven wrote: > On Sat, 24 Sep 2005, TRANS wrote: > > > Whoa. almost had me fooled into thinking you managed: > > > > @x.__.dup.__ > > > > in place of > > > > @x.__dup__ > > > > :-) > > Well, I could you know, with a little tweaking. __ wraps @x in a > BackToTheBasics object. dup calls the original dup on @x and wraps it > again in a BackToTheBasics object. __ on this BackToTheBasics then unwraps > it. And then you've got the above! Genuis. But lets not go there ;-) > >> Implementation is simply this: > >> > >> class BackToTheBasics > >> def initialize(obj) > >> @self = obj > >> end > >> ['dup', 'send'].each do |m| > >> module_eval %Q{ > >> def #{m}(*args, &blk) > >> Kernel.instance_method(#{m.dump}).bind(@self).call(*args, &blk) > >> end > >> } > >> end > >> end > >> > >> module Kernel > >> def __ > >> @__ ||= BackToTheBasics.new(self) > >> end > >> end > > > > Nice. That's a very viable solution. Mind if I drop it on Matz to see > > what he thinks? > > Please go ahead. Cool. > >> Well, it's a different kind of use case. I could do "obj as Proxy" and > >> pass it around to code that will see it as a Proxy. This is irrespective > >> of whatever namespace that code is in, or whatever namespace that code > >> thinks it's seeing. It's a more of a dynamic version of namespaces > >> (namespaces are quite static). > > > > I think I see. Sort of like attatching the namespace to the object? > > Yup, sort of. It's a bit like the BackToTheBasics above: it is wrapped in > an object that calls the methods through the namespace it was given at its > creation. So the BackToTheBasics thing would just use the Kernel > namespace. or whatever we'd call it. Ah, I see. I've been using my Functor to partially immitate Namespaces --now I see by adding a binding module like this we get (limited) Roles too. In fact just today I had renamed the Module#superfunc (aka #supers or #superup) to #as. Thus: x.as(Kernel).dup > Well, VB back in those days alreayd allowed drawing forms (that's what > they called windows, I don't know if they still do that) and drawing > buttons on it and then attaching actions to those buttons and all. Yes, it > was much fun to play with. I built a mastermind game in it once. And a > program that could add/subtract/multiply/divide multiple precision > numbers. I reimplemented that in Pascal once to calculate lots of digits > of pi. I don't remember how far I got. I think I set up the program to get > to a million digits, but due to lack of patience, I decreased that, but I > don't remember by how much. Another game I built in VB was a checkers > game. But I'm pretty sure these programs don't run anymore on today's > Windows systems. It was Windows 3.0 back then. Yep, that's way back. I've done quite a bit of VB coding since about 3.1. I wrote a small professional bookstore accounting application in it for instance, among other things. The langauge and tools itself were pretty good, it was the whole Windows thing --dll hell, etc, and the steep $ (cost), that really drove me crazy. When I started using OSS like postgresql on the backend I got interoperability problems that I think MS purposefully put there. That sealed it's fate and I learned Ruby :-) Unfortuately this is why I know so little C/C++. While I taught it to myself in HS reading K&R and took a class or two on it in college, writing a poor AI Chess program, I never used it beyond that --well, I suppose that's both good and bad. > > BTW to you watch ruby-core mailing list? I posted an idea for close blocks: > > > > Class.new [ > > #... > > ] > > > > If Hash can share it's literal notation, why not array? But there > > needs to be a way to pass in specific vars. > > I'm watching ruby-core indeed. Still, the above notation does not convey > the idea of closedness to me, so I'm not too keen about it. Okay, but were running out of possibilites on this one, I think! :-) > About passing in variables, and keeping variables in, maybe something > like this: > > Class.new |a, b| [ |c, d| > # ... > ] Eek, that makes me dizzy. > Well, it's not ideal, but c and d are clearly inside, and a and b clearly > come from the outside. Of course it don't jive with Ruby's current block > syntax. Combined with that, I think it gets to complicated. Too much > punctuation lying around. I don't know, to me it seems that the simple > rules of completely closed vs completely open or still best. Only that completely closed has some limitations for initializing loop vars: i = 0 collect [ |a| a + ( i += 1) ] > Part of the problem is that in Ruby variables are not declared. If they > were, more combination of openness and closedness would be possible. So > maybe local variables need a declaration. For example: > > Class.new { > local a, b > } > > For closed blocks, we need the inverse: > > Class.new [ > global a, b > ] That makes sense. While I'm glad Matz shuns declarations I think sometimes maybe its a little over done. The above is very clear, which makes it better then any fancy punctuated syntax I've seen or been able to imagine. > I don't know about the word global. Maybe 'escape' or 'escaping' is > better. What about #grab? With matz' new notation: Class.new -> (c, d) [ grab a,b ] Hmm... That could get a,b from above scope but not effect them after the fact, perhaps? Then another term that could be used for otherwise, like #share Class.new -> (c, d) [ share a,b ] I'm trying to keep in mind too that in future Ruby, vars defined in the block will no longer need be defined prior to the block to conitnue on to the rest of outer scope. T. From calamitas at advalvas.be Sat Sep 24 18:18:17 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sun, 25 Sep 2005 00:18:17 +0200 (CEST) Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: <4b6f054f050924124660760250@mail.gmail.com> References: <4b6f054f050924124660760250@mail.gmail.com> Message-ID: On Sat, 24 Sep 2005, TRANS wrote: > Today George of Nitro asked me to alias #include to #is: > > class Foo > is Bar > end I like this too. It's very nice for things like Enumerable: class Foo is Enumerable end If the name of a module is a noun, #is_a and #is_an are nice to. And if you're afraid of people accidentally overriding these methods, you can also alias it to #walks_and_quacks_like_a ;-) Actually, I'm not completely joking about this, it is one of those nice details that can make code more fun to read! > I like it and saw no ready reason now to support it so I added it to > Nano. This got me to thinking about how modules are included. I really > tire of jumping through hoops using Module#included to tell it I want > class method included too. The use of #extend seems backward --why > should the class dictate how the module effect it? (except under > special circumstances). I think that undermines the whole idea of > "enpsulated module". > > So I propose we get on with it and offer some declarations: > > module M > function > def f ; "F" ; end > extends > def x ; "X" ; end > inherits > def y ; "Y" ; end > end > > 'function' is the same as current module_function and would be the > default. It both acts as a non-extending module function and an > instance-level inheritable. So, > > M.f #=> "F" > M.x #=> error > M.y #=> error > > class X > is M > end > > X.x #=> "X" > X.new.y #=> "Y" > X.f #=> error > X.new.f #=> "F" (albeit it is private) You know, maybe we can look at this slightly differently. At the moment, this works: class A def x ; "x" ; end def self.y ; "y" ; end end class B < A ; end A.new.x A.y B.new.x B.y Why does this work? Because this is true: B.is_a? A.metaclass What does this mean? It means that B's metaclass is a subclass of A's metaclass, although they've tried to cover up this fact. For example B.metaclass.superclass will return Class.metaclass and not A.metaclass, but A.metaclass is there in the chain. (You should remember that picture). Now why oh why is the same thing not done on module inclusion? It seems to make sense to do it, right? And it would solve part of your problem. Of course it is not as powerful as your proposal above, but it goes part of the way and is simpler, so I say do it like that and build extra functionality on top of that. Also, if you want to go the above way, please let these new functions have block forms too, or only block forms as far as I'm concerned. I find the way things are now for private and all too magical, and also emacs will indent better. So IMO the above would look better like this: module M function { def f ; "F" ; end } extends { def x ; "X" ; end } inherits { def y ; "Y" ; end } end Sure it adds a few more lines, but I find this a lot clearer. > Also I would like to move foward on ultimately replacing the #methods > and #instance_methods to take symbol query parameters, instead of have > all the other methods: public_methods, private_methods, etc. In fact > if methods tool on more of a 1st class role (even if faked). Then > perhaps: > > M.methods.select { |m| m.access == :private } > > Of course I still am interesed in throwing out the current > private/protected/public for now and start fresh later with a truer > form. Well, I think it would still be nice for public_methods etc to remain, but just add a deneral select method (possibly even just as Module#methods). The reason is that IMO these are still generally useful methods. I usually only need either public_methods, or private_methods, or public_instance_methods, and it makes little sense to all of a sudden have to write twice as much code to do the same thing. > Finally, I'm curious. And I know this might seem like a shocker. But I > often wonder about the fact the #alias doesn't need a comma separated > list of arguments. I know it's special but I wonder if it might be > generally applicable? > > class X > def intialize( a b c ) > #... > end > end > > X.new :A :B :C Well, it causes ambiguity. "a b c d" can be parsed as follows: a(b(c(d))) a(b(c,d)) a(b(c),d) a(b,c(d)) a(b,c,d) Of course, if you don't want commas, you could always employ a Lispy kind of syntax: (X.new :A :B :C) Or else require brackets around the parameters at all times: X.new(:A :B :C) I don't think you can get away with dropping these commas without introducing extra brackets, or some other way of disambiguating thing. Peter From transfire at gmail.com Sat Sep 24 20:19:17 2005 From: transfire at gmail.com (TRANS) Date: Sat, 24 Sep 2005 20:19:17 -0400 Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: References: <4b6f054f050924124660760250@mail.gmail.com> Message-ID: <4b6f054f05092417191bff2d60@mail.gmail.com> On 9/24/05, Peter Vanbroekhoven wrote: > On Sat, 24 Sep 2005, TRANS wrote: > > > Today George of Nitro asked me to alias #include to #is: > > > > class Foo > > is Bar > > end > > I like this too. It's very nice for things like Enumerable: > > class Foo > is Enumerable > end > > If the name of a module is a noun, #is_a and #is_an are nice to. That occured to me, but I thought 'is' probably is enough, and encourage the idea that modules are more "adjective" and classes "noun", after all there has to be some substantial difference ;-) (Yes, I'm half joking too). > And if > you're afraid of people accidentally overriding these methods, you can > also alias it to #walks_and_quacks_like_a ;-) Actually, I'm not completely > joking about this, it is one of those nice details that can make code more > fun to read! Duck! It's a Duck module! :-) Well feel free to alias away. > > I like it and saw no ready reason now to support it so I added it to > > Nano. This got me to thinking about how modules are included. I really > > tire of jumping through hoops using Module#included to tell it I want > > class method included too. The use of #extend seems backward --why > > should the class dictate how the module effect it? (except under > > special circumstances). I think that undermines the whole idea of > > "enpsulated module". > > > > So I propose we get on with it and offer some declarations: > > > > module M > > function > > def f ; "F" ; end > > extends > > def x ; "X" ; end > > inherits > > def y ; "Y" ; end > > end > > > > 'function' is the same as current module_function and would be the > > default. It both acts as a non-extending module function and an > > instance-level inheritable. So, > > > > M.f #=> "F" > > M.x #=> error > > M.y #=> error > > > > class X > > is M > > end > > > > X.x #=> "X" > > X.new.y #=> "Y" > > X.f #=> error > > X.new.f #=> "F" (albeit it is private) > > You know, maybe we can look at this slightly differently. At the moment, > this works: > > class A > def x ; "x" ; end > def self.y ; "y" ; end > end > > class B < A ; end > > A.new.x > A.y > B.new.x > B.y > > Why does this work? Because this is true: > > B.is_a? A.metaclass > > What does this mean? It means that B's metaclass is a subclass of A's > metaclass, although they've tried to cover up this fact. For example > B.metaclass.superclass will return Class.metaclass and not A.metaclass, > but A.metaclass is there in the chain. (You should remember that picture). > Now why oh why is the same thing not done on module inclusion? It seems to > make sense to do it, right? And it would solve part of your problem. Of > course it is not as powerful as your proposal above, but it goes part of > the way and is simpler, so I say do it like that and build extra > functionality on top of that. Although a problem here is that at time one does include the instance methods of the the module, but also uses the module as a separate module namespace. Abstractly something like: module M def self.store @store ||= {} end def store(key) M.store[key] end end class A include M end And not interested in A gaining a store. Actually I think that might be why Matz did it this way. One of the thing's I'm also trying to do is give module a distinct nature, different from class. Otherwise I'm inclided to remove the distinction altogether. This is a way is like the block issure as well. Being inclined not to add declarations we are loosing out a lot of flexibility. > Also, if you want to go the above way, please let these new functions have > block forms too, or only block forms as far as I'm concerned. I find the > way things are now for private and all too magical, and also emacs will > indent better. I've recently started to look at like if ... then ... else ... end, or begin ... rescue ... ensure ... end, etc. But the bracket notation works too. Then I wonder also about: module M function ... end extends ... end end In a way I think that's what the former endless notion is, it's just that it doesn't do any good for them to be embedded in one another so the end is implied. > So IMO the above would look better like this: > > module M > function { > def f ; "F" ; end > } > extends { > def x ; "X" ; end > } > inherits { > def y ; "Y" ; end > } > end > > Sure it adds a few more lines, but I find this a lot clearer. > > > Also I would like to move foward on ultimately replacing the #methods > > and #instance_methods to take symbol query parameters, instead of have > > all the other methods: public_methods, private_methods, etc. In fact > > if methods tool on more of a 1st class role (even if faked). Then > > perhaps: > > > > M.methods.select { |m| m.access == :private } > > > > Of course I still am interesed in throwing out the current > > private/protected/public for now and start fresh later with a truer > > form. > > Well, I think it would still be nice for public_methods etc to remain, but > just add a deneral select method (possibly even just as Module#methods). > The reason is that IMO these are still generally useful methods. I usually > only need either public_methods, or private_methods, or > public_instance_methods, and it makes little sense to all of a sudden have > to write twice as much code to do the same thing. Oh sorry, I did not full express that. M.methods( :public ) Would give you what you want --symbol keys to query on. BTW, in Nano there is a interesting addtion to the symbol class as a strart to add logic. You can use it with #methods (also in nano) M.methods( ~:public ) meaning NOT public. What it does is simply alter the symbol to :"~public". And you can query it with symbol#not?. > > Finally, I'm curious. And I know this might seem like a shocker. But I > > often wonder about the fact the #alias doesn't need a comma separated > > list of arguments. I know it's special but I wonder if it might be > > generally applicable? > > > > class X > > def intialize( a b c ) > > #... > > end > > end > > > > X.new :A :B :C > > Well, it causes ambiguity. "a b c d" can be parsed as follows: > > a(b(c(d))) > a(b(c,d)) > a(b(c),d) > a(b,c(d)) > a(b,c,d) > > Of course, if you don't want commas, you could always employ a Lispy kind > of syntax: > > (X.new :A :B :C) > > Or else require brackets around the parameters at all times: > > X.new(:A :B :C) > > I don't think you can get away with dropping these commas without > introducing extra brackets, or some other way of disambiguating thing. Sure, additional brackets would come into play, I realize, but would suitble default behavior be possible? I mean is it possible for both means to live harmonously? Every language I've ever seen does it one way or the other, commas or spaces. It never occured to me before, but why not both? But perhaps there are very good reasons. Interestingly: def a(x) ; x+1 ; end a a a a 3 (irb):5: warning: parenthesize argument(s) for future version (irb):5: warning: parenthesize argument(s) for future version (irb):5: warning: parenthesize argument(s) for future version => 7 So that behavior is about to change. T. From calamitas at advalvas.be Sat Sep 24 20:30:01 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sun, 25 Sep 2005 02:30:01 +0200 (CEST) Subject: [suby-talk] Meta programming from without In-Reply-To: <4b6f054f0509241326375e07d1@mail.gmail.com> References: <4b6f054f050920072432ff14@mail.gmail.com> <4b6f054f050921145555f76ead@mail.gmail.com> <4b6f054f05092313491040ce3@mail.gmail.com> <4b6f054f050923205527c12645@mail.gmail.com> <4b6f054f0509241217d57d0b3@mail.gmail.com> <4b6f054f0509241326375e07d1@mail.gmail.com> Message-ID: On Sat, 24 Sep 2005, TRANS wrote: > Genuis. But lets not go there ;-) :-) > Ah, I see. I've been using my Functor to partially immitate Namespaces > --now I see by adding a binding module like this we get (limited) > Roles too. In fact just today I had renamed the Module#superfunc (aka > #supers or #superup) to #as. Thus: > > x.as(Kernel).dup Yup, that ought to do it. So you already had a solution :-) > Yep, that's way back. I've done quite a bit of VB coding since about > 3.1. I wrote a small professional bookstore accounting application in > it for instance, among other things. The langauge and tools itself > were pretty good, it was the whole Windows thing --dll hell, etc, and > the steep $ (cost), that really drove me crazy. When I started using > OSS like postgresql on the backend I got interoperability problems > that I think MS purposefully put there. That sealed it's fate and I > learned Ruby :-) Unfortuately this is why I know so little C/C++. > While I taught it to myself in HS reading K&R and took a class or two > on it in college, writing a poor AI Chess program, I never used it > beyond that --well, I suppose that's both good and bad. Well, it's not really that hard to learn. OK, so I program in C++ 'at daytime', but it's not like I'm any good at it. Partially because I hate C++ ;-) C is a lot easier, and I'm pretty good at that. But compared to Ruby, it's not fun at all. It's tedious most of the time. >>> BTW to you watch ruby-core mailing list? I posted an idea for close blocks: >>> >>> Class.new [ >>> #... >>> ] >>> >>> If Hash can share it's literal notation, why not array? But there >>> needs to be a way to pass in specific vars. >> >> I'm watching ruby-core indeed. Still, the above notation does not convey >> the idea of closedness to me, so I'm not too keen about it. > > Okay, but were running out of possibilites on this one, I think! :-) I know. I don't think it is really solvable by any punctuation. Whatever you come up with, I'll say the same thing. >> About passing in variables, and keeping variables in, maybe something >> like this: >> >> Class.new |a, b| [ |c, d| >> # ... >> ] > > Eek, that makes me dizzy. Ah, but wait, we haven't talked yet about variables that can leave the block or seep in from behind, so the general case looks like this: Class.new |a, b| [ |c, d| # ... (e, f) ] (g, h) > Only that completely closed has some limitations for initializing loop vars: > > i = 0 > collect [ |a| a + ( i += 1) ] I know, for blocks it's bad. >> Part of the problem is that in Ruby variables are not declared. If they >> were, more combination of openness and closedness would be possible. So >> maybe local variables need a declaration. For example: >> >> Class.new { >> local a, b >> } >> >> For closed blocks, we need the inverse: >> >> Class.new [ >> global a, b >> ] > > That makes sense. While I'm glad Matz shuns declarations I think > sometimes maybe its a little over done. The above is very clear, which > makes it better then any fancy punctuated syntax I've seen or been > able to imagine. My thoughts exactly. I like that better even than Matz' local(a,b) { ... } syntax. Problem with that is that it makes things look uglier when using the block: some_meth(*params) local(a,b) { ... }. This is hard to read. >> I don't know about the word global. Maybe 'escape' or 'escaping' is >> better. > > What about #grab? With matz' new notation: > > Class.new -> (c, d) [ > grab a,b > ] > > Hmm... That could get a,b from above scope but not effect them after > the fact, perhaps? Then another term that could be used for otherwise, > like #share > > Class.new -> (c, d) [ > share a,b > ] > > I'm trying to keep in mind too that in future Ruby, vars defined in > the block will no longer need be defined prior to the block to > conitnue on to the rest of outer scope. share is nice. Definitely better than grab. I like it! :-) Peter From calamitas at advalvas.be Sun Sep 25 10:02:07 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sun, 25 Sep 2005 16:02:07 +0200 (CEST) Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: <4b6f054f05092417191bff2d60@mail.gmail.com> References: <4b6f054f050924124660760250@mail.gmail.com> <4b6f054f05092417191bff2d60@mail.gmail.com> Message-ID: On Sat, 24 Sep 2005, TRANS wrote: > That occured to me, but I thought 'is' probably is enough, and > encourage the idea that modules are more "adjective" and classes > "noun", after all there has to be some substantial difference ;-) > (Yes, I'm half joking too). Well, I think class names being nouns sounds generally about right. I'm not sure about module names always being adjectives. Singleton is an example. Maybe that should be named Singletonlike then. But whether it should be a noun or adjective depends on what the module is supposed to do. > Although a problem here is that at time one does include the instance > methods of the the module, but also uses the module as a separate > module namespace. Abstractly something like: > > module M > def self.store > @store ||= {} > end > def store(key) > M.store[key] > end > end > > class A > include M > end > > And not interested in A gaining a store. Actually I think that might > be why Matz did it this way. OK, but what's the difference with this? class M def self.store @store ||= {} end def store(key) M.store[key] end end class A < M end Then why did Matz do that that way? To me there's no difference with modules as your example above is certainly not specific to modules. > One of the thing's I'm also trying to do is give module a distinct > nature, different from class. Otherwise I'm inclided to remove the > distinction altogether. This is a way is like the block issure as > well. Being inclined not to add declarations we are loosing out a lot > of flexibility. But I don't see why modules in this case deserve a distinct behavior. If different behavior is desirable for modules, it is so too for classes. Or else I'm being dense again. > I've recently started to look at like if ... then ... else ... end, or > begin ... rescue ... ensure ... end, etc. But the bracket notation > works too. Then I wonder also about: > > module M > > function > ... > end > > extends > ... > end > > end I know you wonder about that too when I propose these block versions. But that's immediately a completely different ball game. For that to work, function and extends need to be keywords. And the problem is that it doesn't stop with the above. instance_eval should also have that kind of form then. And basically any method that only takes a block and no other arguments. I know you like uniformity, either there's a do everywhere or nowhere, but the only way to do that is put a do everywhere. Nice thing about that is that it frees module/class/if/while/begin and possibly others as keywords. Of course a change like this is not backwards compatible with Ruby and may not be something people have been waiting for. Would it make sense to just have the same behavior for modules as classes have now, and then use the singleton methods of the meta classes for the purpose of those class-local singleton methods? The reason I'm proposing this is because what you propose above is a big change, in more than one way. It depends on the answers to a few questions though. For example what happens when one does a "def self.m ; end" inside a module? Do the "modifiers" affect this too? How? Or would singleton methods for modules just be disallowed? A second remark is that private/public/protected are just flags. Is the idea that the above are just flags too? If so, expect a decent speed hit from this. But if they are just flags, then know that a module cannot have an instance method and a 'function' with the same name. More specifically this would mean that Kernel cannot both have a class instance method and a class 'function', so either obj.class or SomeModule.class is necessarily broken. So they really need to be more than just flags. But what should they be then? > In a way I think that's what the former endless notion is, it's just > that it doesn't do any good for them to be embedded in one another so > the end is implied. I'm not sure if the point really should be to avoid things that don't make sense. As it is now, 10 consecutive public/private/protected statements are possible too, although they do no good either. They could be nested, but any good programmer will avoid doing that unless it is what he wants. > Oh sorry, I did not full express that. > > M.methods( :public ) > > Would give you what you want --symbol keys to query on. > > BTW, in Nano there is a interesting addtion to the symbol class as a > strart to add logic. You can use it with #methods (also in nano) > > M.methods( ~:public ) > > meaning NOT public. What it does is simply alter the symbol to > :"~public". And you can query it with symbol#not?. Hehe, looks funny. Would it make sense to use symbols as the start of something to build logical, symbolic formulas? So ":public and not :private" would work to. It creates a logical formula that represents just this. This could possibly be extended to polynomial things, so "5 * :x * :y" would work too. > Sure, additional brackets would come into play, I realize, but would > suitble default behavior be possible? I mean is it possible for both > means to live harmonously? Every language I've ever seen does it one > way or the other, commas or spaces. It never occured to me before, but > why not both? But perhaps there are very good reasons. Interestingly: > > def a(x) ; x+1 ; end > a a a a 3 > > (irb):5: warning: parenthesize argument(s) for future version > (irb):5: warning: parenthesize argument(s) for future version > (irb):5: warning: parenthesize argument(s) for future version > => 7 > > So that behavior is about to change. Well, even a(a 3) gives that warning. But I don't know if both means of specifying arguments can be combined harmoniously. It's something I need to think about some more. Peter From transfire at gmail.com Sun Sep 25 11:33:27 2005 From: transfire at gmail.com (TRANS) Date: Sun, 25 Sep 2005 11:33:27 -0400 Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: References: <4b6f054f050924124660760250@mail.gmail.com> <4b6f054f05092417191bff2d60@mail.gmail.com> Message-ID: <4b6f054f05092508333e4366bf@mail.gmail.com> On 9/25/05, Peter Vanbroekhoven wrote: > On Sat, 24 Sep 2005, TRANS wrote: > Well, I think class names being nouns sounds generally about right. I'm > not sure about module names always being adjectives. Singleton is an > example. Maybe that should be named Singletonlike then. But whether it > should be a noun or adjective depends on what the module is supposed to > do. 'is Singleton' sounds right though. Nouns can be used as adjectives, so I think it works okay, eg. 'is Elephant' > > Although a problem here is that at time one does include the instance > > methods of the the module, but also uses the module as a separate > > module namespace. Abstractly something like: > > > > module M > > def self.store > > @store ||= {} > > end > > def store(key) > > M.store[key] > > end > > end > > > > class A > > include M > > end > > > > And not interested in A gaining a store. Actually I think that might > > be why Matz did it this way. > > OK, but what's the difference with this? > > class M > def self.store > @store ||= {} > end > def store(key) > M.store[key] > end > end > > class A < M > end > > Then why did Matz do that that way? To me there's no difference with > modules as your example above is certainly not specific to modules. In the first module example A.store #=> error In the later class example A.store #=> {} > > One of the thing's I'm also trying to do is give module a distinct > > nature, different from class. Otherwise I'm inclided to remove the > > distinction altogether. This is a way is like the block issure as > > well. Being inclined not to add declarations we are loosing out a lot > > of flexibility. > > But I don't see why modules in this case deserve a distinct behavior. If > different behavior is desirable for modules, it is so too for classes. Or > else I'm being dense again. No, you're right. It would apply to classes too --as long as Class remains a sublcass of Module, it would have too. Though there is the inheritance distinction even now. But I suppose this could be used on classes to determine which methods effect the sublclass. Hmm... There seems to be four kinds of methods in this regard. 1) instance methods 2) class methods that get inherited 3) class methods that do not, and 4) local methods (instance methods that do not get inherited). Of course we don't currently have the 4th kind. And the 3rd is only available in Modules. And to get the 1st in Modules you have to do some trickery. The common fatcor is inheritablilty, so maybe we just need a declaration: inhertiable vs. noniheritable. Could 'local' also work here? Or do we need a different term? Well, just as an example: class B local def self.x ... end end class A < B end A.x #=> error > > I've recently started to look at like if ... then ... else ... end, or > > begin ... rescue ... ensure ... end, etc. But the bracket notation > > works too. Then I wonder also about: > > > > module M > > > > function > > ... > > end > > > > extends > > ... > > end > > > > end > > I know you wonder about that too when I propose these block versions. But > that's immediately a completely different ball game. For that to work, > function and extends need to be keywords. And the problem is that it > doesn't stop with the above. instance_eval should also have that kind of > form then. And basically any method that only takes a block and no other > arguments. I know you like uniformity, either there's a do everywhere or > nowhere, but the only way to do that is put a do everywhere. Nice thing > about that is that it frees module/class/if/while/begin and possibly > others as keywords. Of course a change like this is not backwards > compatible with Ruby and may not be something people have been waiting > for. Sadly tis true. And I imagine it's just too much overhead to have methods that take only a block parameter to allow that form --in effect becoming keywords. > Would it make sense to just have the same behavior for modules as classes > have now, and then use the singleton methods of the meta classes for the > purpose of those class-local singleton methods? The reason I'm proposing > this is because what you propose above is a big change, in more than one > way. It depends on the answers to a few questions though. For example what > happens when one does a "def self.m ; end" inside a module? Do the > "modifiers" affect this too? How? Or would singleton methods for modules > just be disallowed? Well that depends on the direction we take. The idea above is really just one of deciding which methods are inheritable or not. So (I think) it's a relatively minor change. The other option is that modules are quite different things from classes --I assume you read my blog post on the idea of closing the Scary Door. Yes, in that case it's a much bigger change, in which doing "def self.m ; end" in a module would not be any different from doing "def m ; end." --they exist at both levels b/c modules always extend themselves. This has the advantage of greatly simplifying the whole class inheritance structure, but at the expense of not being able to use modules's class and instance levels independently (rather one would require two separate modules). And of course this relates to the whole self-shimmying idea too. Actually the two ideas are not mutually exlusive. The idea of inheritable vs. non-inheritable method could still apply if the later were used. >A second remark is that private/public/protected are > just flags. Is the idea that the above are just flags too? If so, expect a > decent speed hit from this. But if they are just flags, then know that a > module cannot have an instance method and a 'function' with the same name. > More specifically this would mean that Kernel cannot both have a class > instance method and a class 'function', so either obj.class or > SomeModule.class is necessarily broken. So they really need to be more > than just flags. But what should they be then? Does the above help decide which? I think flags is all that is probably needed, but I'm not sure --pehaps separate method tables is better? Actually after reading this, I realize I'm not exactly sure what is module_function is any more. I thought it just meant that the instance method was copied to the class level. But after discovering module_functions can't be looked up using #instance_methods, I don't know anymore. > I'm not sure if the point really should be to avoid things that don't make > sense. As it is now, 10 consecutive public/private/protected statements > are possible too, although they do no good either. They could be nested, > but any good programmer will avoid doing that unless it is what he wants. That's true. > Hehe, looks funny. Would it make sense to use symbols as the start of > something to build logical, symbolic formulas? So ":public and > not :private" would work to. It creates a logical formula that represents > just this. Yes. I was thinking along those lines. Like: :public & :private & ~:inherited > This could possibly be extended to polynomial things, so "5 * > :x * :y" would work too. Interesting. Hadn't though of that. Symbol could be Symbolic Formula? Well, we do call it Symbolic Logic after all :-) > Well, even a(a 3) gives that warning. Right. And why so? Apparrently Matz wants to move toward always using the parens, at least on any inner call. Once that's done, it seems like non-comma notation might be possible. > But I don't know if both means of specifying arguments can be combined > harmoniously. It's something I need to think about some more. Me too. Edge cases are often difficult to phathom. T. From calamitas at advalvas.be Sun Sep 25 15:26:10 2005 From: calamitas at advalvas.be (Peter Vanbroekhoven) Date: Sun, 25 Sep 2005 21:26:10 +0200 (CEST) Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: <4b6f054f05092508333e4366bf@mail.gmail.com> References: <4b6f054f050924124660760250@mail.gmail.com> <4b6f054f05092417191bff2d60@mail.gmail.com> <4b6f054f05092508333e4366bf@mail.gmail.com> Message-ID: On Sun, 25 Sep 2005, TRANS wrote: > 'is Singleton' sounds right though. Nouns can be used as adjectives, > so I think it works okay, eg. 'is Elephant' Realized that myself too after sending it. Besides, it is possible to omit articles anyway in some ways of writing ("is not best thing to do" instead of "this is not the best thing to do"). >>> Although a problem here is that at time one does include the instance >>> methods of the the module, but also uses the module as a separate >>> module namespace. Abstractly something like: >>> >>> module M >>> def self.store >>> @store ||= {} >>> end >>> def store(key) >>> M.store[key] >>> end >>> end >>> >>> class A >>> include M >>> end >>> >>> And not interested in A gaining a store. Actually I think that might >>> be why Matz did it this way. >> >> OK, but what's the difference with this? >> >> class M >> def self.store >> @store ||= {} >> end >> def store(key) >> M.store[key] >> end >> end >> >> class A < M >> end >> >> Then why did Matz do that that way? To me there's no difference with >> modules as your example above is certainly not specific to modules. > > In the first module example > > A.store #=> error > > In the later class example > > A.store #=> {} That was exactly my point. For modules, the behavior is different from classes _now_, but the reason for modules to behave as they do now can be applied to classes as well, so why isn't it? Why is there this difference? >>> One of the thing's I'm also trying to do is give module a distinct >>> nature, different from class. Otherwise I'm inclided to remove the >>> distinction altogether. This is a way is like the block issure as >>> well. Being inclined not to add declarations we are loosing out a lot >>> of flexibility. >> >> But I don't see why modules in this case deserve a distinct behavior. If >> different behavior is desirable for modules, it is so too for classes. Or >> else I'm being dense again. > > No, you're right. It would apply to classes too --as long as Class > remains a sublcass of Module, it would have too. Though there is the > inheritance distinction even now. But I suppose this could be used on > classes to determine which methods effect the sublclass. Hmm... > > There seems to be four kinds of methods in this regard. 1) instance > methods 2) class methods that get inherited 3) class methods that do > not, and 4) local methods (instance methods that do not get > inherited). Of course we don't currently have the 4th kind. And the > 3rd is only available in Modules. And to get the 1st in Modules you > have to do some trickery. > > The common fatcor is inheritablilty, so maybe we just need a > declaration: inhertiable vs. noniheritable. Could 'local' also work > here? Or do we need a different term? Well, just as an example: > > class B > local > def self.x > ... > end > end > > class A < B > end > > A.x #=> error I got to this point too. But there's one thing that bothers me. I mean, although I can see the point of this at the level of classes and modules, it makes less sense to me at the level of objects: class A local def x end end class B < A end A.new.x # => OK B.new.x # => error This local thing is almost the inverse of C++ virtual. I don't know if that is a good thing. But arguable, that it could be. I'm just pointing out that these are not the local methods we once talked about, or at least not what I understood from it. In any case, I think this rises the question of what the complete semantics of this is. Can a class have a local instance method and a normal instance method with the same name? If so, which takes precedence? I assume the local ones. That would make these local methods behave as if, after all classes and normal methods are defined, you do this: class A end class B < A end class A < A def x # local method end end So: B.new.x # => error A.new.x # => OK If a class can't have a normal and local method with the same name (like we can't have a private and public method by the same name), then does it behave like private in the sense that local methods hide underlying normal methods: class A def m end end class B < A local def m end end class C < B end C.new.m #=> error or not? It's a bit the same as classic private vs namespace private (or true private). > Sadly tis true. And I imagine it's just too much overhead to have > methods that take only a block parameter to allow that form --in > effect becoming keywords. Well, the point of keywords is that that is known upfront. If it depends on the actual method that is called, it's not just expensive, it's plain impossible. Well, unless the syntax is really completely totally changed, and then it might indeed become a bit inefficient, although I don't know if that is guaranteed. > Well that depends on the direction we take. The idea above is really > just one of deciding which methods are inheritable or not. So (I > think) it's a relatively minor change. And I like that better than your original idea. Although there are still some questions to be answered. > The other option is that modules are quite different things from > classes --I assume you read my blog post on the idea of closing the > Scary Door. Yes, in that case it's a much bigger change, in which > doing "def self.m ; end" in a module would not be any different from > doing "def m ; end." --they exist at both levels b/c modules always > extend themselves. This has the advantage of greatly simplifying the > whole class inheritance structure, but at the expense of not being > able to use modules's class and instance levels independently (rather > one would require two separate modules). And of course this relates to > the whole self-shimmying idea too. Well, the problem is that the way things are now is pretty much a natural consequence of classes being objects and objects having singleton classes. I mean, singleton classes/methods are what "def self.m ; end" is all about. Abolishing that notation does not simplify the inheritance structure, unless you abolish singleton classes completely. But whether that simplifies things is not so clear. I mean, you can simplify anything by taking away features, but that can make it harder to use. I suppose those are two opposing forces and there's a balance somewhere. Seeing that many people find it nice to be able to define methods on a single object (be that modules or classes or objects (which modules and classes are)), I find it hard to believe we have too many features. Of course we could just introduce the rule that classes and modules can't have singleton methods, but that introduces asymetry that may be even more confusing. Maybe this is because I don't understand the confusing that it is supposed to cause. The only confusion to me is why singleton methods are inherited with classes and not with modules. For the rest, the rules are quite clear, once you've learned them. What I'm afraid of is though that the idea of local methods may make things more complicated again. In a sense, maybe it's not that bad that one needs to do a separate #include and a separate #extend. It makes it more explicit, and does not require more complicated stuff. I know complicated is something slightly subjective, but still. I get the feeling I should think about this a bit more. Hmmm, maybe... Aren't classes and modules about inheritance? Question is them: do the non-inheritable methods actually belong in a class or module then? > Actually the two ideas are not mutually exlusive. The idea of > inheritable vs. non-inheritable method could still apply if the later > were used. Yep, both ideas are orthogonal. > Does the above help decide which? I think flags is all that is > probably needed, but I'm not sure --pehaps separate method tables is > better? That's what I don't know. But like I said, it's a bit like privateness. What do we like there? > Actually after reading this, I realize I'm not exactly sure what is > module_function is any more. I thought it just meant that the instance > method was copied to the class level. But after discovering > module_functions can't be looked up using #instance_methods, I don't > know anymore. Try #private_instance_methods. For some reason, they are made private. irb(main):001:0> module M irb(main):002:1> def m irb(main):003:2> end irb(main):004:1> module_function :m irb(main):005:1> end => M irb(main):006:0> M.methods(false) => ["m"] irb(main):007:0> M.private_instance_methods(false) => ["m"] > Yes. I was thinking along those lines. Like: > > :public & :private & ~:inherited I'd use && instead of &. & is bitwise and, kind of weird for logical formulas. >> This could possibly be extended to polynomial things, so "5 * >> :x * :y" would work too. > > Interesting. Hadn't though of that. Symbol could be Symbolic Formula? > Well, we do call it Symbolic Logic after all :-) Yup. So, another addition to Mega? I wouldn't mind trying to implement all this you know. >> Well, even a(a 3) gives that warning. > > Right. And why so? Apparrently Matz wants to move toward always using > the parens, at least on any inner call. Once that's done, it seems > like non-comma notation might be possible. > >> But I don't know if both means of specifying arguments can be combined >> harmoniously. It's something I need to think about some more. > > Me too. Edge cases are often difficult to phathom. Well, let's see. I think this would be ambiguous if both "m a, b, c" and "m(a b c)" is allowed: m(a b) If we don't allow parentheses in one argument methods, I think we are safe because then there's always a comma. However it is not so easy to parse things (for a computer as well as for a human): m(a b,c,d) So "a b" cannot be interpreted as a method call by itself because of the one argument rule, and thus the proper interpretation can only be this: m(a(b,c,d)) But see how I need to reason about this to find this out? But this means that "puts something" is no longer valid. The problem isn't the bracketed form, it's the comma form. I think it's the lack of punctuation between the method name and the first parameter that is the problem. For one thing that means there's no punctuation when there's just one parameter. Ah, but wait, there's still a problem: a b,c d,e,f Is this a(b, c(d,e), f) or a(b, c(d,e,f)) ? Of course as with lambda calculus we can say that a subexpression is taken as long as possible. That would work, as it disambiguates things in general. I don't know if that is good though, I know from personal experience with bachelor students that this is a very hard rule. Peter From transfire at gmail.com Sun Sep 25 17:51:56 2005 From: transfire at gmail.com (TRANS) Date: Sun, 25 Sep 2005 17:51:56 -0400 Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: References: <4b6f054f050924124660760250@mail.gmail.com> <4b6f054f05092417191bff2d60@mail.gmail.com> <4b6f054f05092508333e4366bf@mail.gmail.com> Message-ID: <4b6f054f050925145185205cf@mail.gmail.com> On 9/25/05, Peter Vanbroekhoven wrote: > On Sun, 25 Sep 2005, TRANS wrote: > > > 'is Singleton' sounds right though. Nouns can be used as adjectives, > > so I think it works okay, eg. 'is Elephant' > > Realized that myself too after sending it. Besides, it is possible to omit > articles anyway in some ways of writing ("is not best thing to do" > instead of "this is not the best thing to do"). With #is and #as and units.rb I start to feel as if Nano/Mega is becoming a ... dare I say it? ... a Framework. > That was exactly my point. For modules, the behavior is different from > classes _now_, but the reason for modules to behave as they do now can be > applied to classes as well, so why isn't it? Why is there this difference? I see. I think they differ just to be able to do exactly that, i.e. not have module class methods inherited. So you can use them differently. At least thats my guess. I don't like it though (obviously), whch is why I want to "fix" it somehow. So if they were to act exactly the same were might you put a table related to a module, but wouldn't be inherited? > > The common fatcor is inheritablilty, so maybe we just need a > > declaration: inhertiable vs. noniheritable. Could 'local' also work > > here? Or do we need a different term? Well, just as an example: > > > > class B > > local > > def self.x > > ... > > end > > end > > > > class A < B > > end > > > > A.x #=> error > > I got to this point too. But there's one thing that bothers me. I mean, > although I can see the point of this at the level of classes and modules, > it makes less sense to me at the level of objects: > > class A > local > def x > end > end > > class B < A > end > > A.new.x # => OK > B.new.x # => error > > This local thing is almost the inverse of C++ virtual. I don't know if > that is a good thing. But arguable, that it could be. I'm just pointing > out that these are not the local methods we once talked about, or at least > not what I understood from it. Hmm.. I wan't sure if they were or not. Okay, I think I see... When I say "local" I simply mean methods that are not-inheritable --they are local to the current module/class. OTOH, "private" methods are still in the chain, just not visible from the outside (but also prefereably in their own namespace). So while I generally think of local methods also being private, I guess there's no reason they have to be --though that may not be a "good OOP" combination. But yea, these are two different things. > In any case, I think this rises the question of what the complete > semantics of this is. Can a class have a local instance method and a > normal instance method with the same name? If so, which takes precedence? > I assume the local ones. That would make these local methods behave as if, > after all classes and normal methods are defined, you do this: > > class A > end > > class B < A > end > > class A < A > def x # local method > end > end > > So: > > B.new.x # => error > A.new.x # => OK > > If a class can't have a normal and local method with the same name (like > we can't have a private and public method by the same name), then does it > behave like private in the sense that local methods hide underlying normal > methods: > > class A > def m > end > end > > class B < A > local > def m > end > end > > class C < B > end > > C.new.m #=> error or not? > > It's a bit the same as classic private vs namespace private (or true > private). > > > Sadly tis true. And I imagine it's just too much overhead to have > > methods that take only a block parameter to allow that form --in > > effect becoming keywords. > > Well, the point of keywords is that that is known upfront. If it depends > on the actual method that is called, it's not just expensive, it's plain > impossible. Well, unless the syntax is really completely totally changed, > and then it might indeed become a bit inefficient, although I don't know > if that is guaranteed. Right, I recall now why it is impossible: b/c of the way Ruby parses and b/c Ruby is dynamic. So Ruby can't be sure a method even exists until it is defined, yet it must be able to parse the code that calls that method even it hasn't been defined yet. Just as you mentioned before, Python has an advantage in this regard. > > Well that depends on the direction we take. The idea above is really > > just one of deciding which methods are inheritable or not. So (I > > think) it's a relatively minor change. > > And I like that better than your original idea. Although there are still > some questions to be answered. > > > The other option is that modules are quite different things from > > classes --I assume you read my blog post on the idea of closing the > > Scary Door. Yes, in that case it's a much bigger change, in which > > doing "def self.m ; end" in a module would not be any different from > > doing "def m ; end." --they exist at both levels b/c modules always > > extend themselves. This has the advantage of greatly simplifying the > > whole class inheritance structure, but at the expense of not being > > able to use modules's class and instance levels independently (rather > > one would require two separate modules). And of course this relates to > > the whole self-shimmying idea too. > > Well, the problem is that the way things are now is pretty much a natural > consequence of classes being objects and objects having singleton classes. > I mean, singleton classes/methods are what "def self.m ; end" is all > about. Abolishing that notation does not simplify the inheritance > structure, unless you abolish singleton classes completely. But whether > that simplifies things is not so clear. I mean, you can simplify anything > by taking away features, but that can make it harder to use. I suppose > those are two opposing forces and there's a balance somewhere. Seeing that > many people find it nice to be able to define methods on a single object > (be that modules or classes or objects (which modules and classes are)), I > find it hard to believe we have too many features. Of course we could just > introduce the rule that classes and modules can't have singleton methods, > but that introduces asymetry that may be even more confusing. Maybe this > is because I don't understand the confusing that it is supposed to cause. > The only confusion to me is why singleton methods are inherited with > classes and not with modules. Oh no, I don't intend that we get rid of singleton class, only that it be reduced to one level only --no scary door. The upshot is simply that modules always "extend self". It would be almost exactly as if one did this themselves whenever they used a module: module Foo extend self ... end > For the rest, the rules are quite clear, > once you've learned them. What I'm afraid of is though that the idea of > local methods may make things more complicated again. In a sense, maybe > it's not that bad that one needs to do a separate #include and a separate > #extend. It makes it more explicit, and does not require more complicated > stuff. I know complicated is something slightly subjective, but still. Well it's definately complicate. I've been using Ruby for years now and I still get confused. I may not be the smartest guy around, but it certainly needs something to either simplify or at least make the various levels explict. include vs extend isn;t the problem pers e. After all what does extend do? it includes a module at the singleton level. class X class << self include M end end The problem simply is the difference between including a module and inheriting a class --i.e. the class method aren't included. But I can see a use for that, so I just want to fix the problem while still allowing a way to do that. > I get the feeling I should think about this a bit more. > > Hmmm, maybe... Aren't classes and modules about inheritance? Question is > them: do the non-inheritable methods actually belong in a class or module > then? Well, they're like local vars. They are utility functions. But maybe you are right, maybe non-inheritable methods have no business being there. > > Actually the two ideas are not mutually exlusive. The idea of > > inheritable vs. non-inheritable method could still apply if the later > > were used. > > Yep, both ideas are orthogonal. > > > Does the above help decide which? I think flags is all that is > > probably needed, but I'm not sure --pehaps separate method tables is > > better? > > That's what I don't know. But like I said, it's a bit like privateness. > What do we like there? The last we discussed we had layed out that inheirtance hierarachy, which was interesting. I would say we were leaning toward a separate space, would you? > > Actually after reading this, I realize I'm not exactly sure what is > > module_function is any more. I thought it just meant that the instance > > method was copied to the class level. But after discovering > > module_functions can't be looked up using #instance_methods, I don't > > know anymore. > > Try #private_instance_methods. For some reason, they are made private. Arghh!!!!!!!!!!!!! I know they are private but had totally forgotten #instance_methods is an alias for #public_instance_methods. I was thinkning it returned all of them. Sigh. It's that kind of thing that kills me. I can't believe not one person bothered to tell me that on ruby-talk or ruby-core --I was so frustarated by it --and became rather confused. Well, thanks for finally removing my confusion. T. P.S. I'm going to move the other two topics to separate threads. From transfire at gmail.com Sun Sep 25 18:02:05 2005 From: transfire at gmail.com (TRANS) Date: Sun, 25 Sep 2005 18:02:05 -0400 Subject: [suby-talk] Symbolic Logic Message-ID: <4b6f054f05092515022a765825@mail.gmail.com> On 9/25/05, Peter Vanbroekhoven wrote: > > :public & :private & ~:inherited > > I'd use && instead of &. & is bitwise and, kind of weird for logical > formulas. Only that !, &&, || are not definable methods, but ~, &, | and ^ are. > >> This could possibly be extended to polynomial things, so "5 * > >> :x * :y" would work too. > > > > Interesting. Hadn't though of that. Symbol could be Symbolic Formula? > > Well, we do call it Symbolic Logic after all :-) > > Yup. So, another addition to Mega? I wouldn't mind trying to implement all > this you know. Sure thing! That'd be great! In fact w/ your Prolog background I imagine this is your cup of tea. T. From transfire at gmail.com Sun Sep 25 18:13:48 2005 From: transfire at gmail.com (TRANS) Date: Sun, 25 Sep 2005 18:13:48 -0400 Subject: [suby-talk] "Is" and ideas for moving foward In-Reply-To: References: <4b6f054f050924124660760250@mail.gmail.com> <4b6f054f05092417191bff2d60@mail.gmail.com> <4b6f054f05092508333e4366bf@mail.gmail.com> Message-ID: <4b6f054f050925151369503793@mail.gmail.com> On 9/25/05, Peter Vanbroekhoven wrote: > >> Well, even a(a 3) gives that warning. > > > > Right. And why so? Apparrently Matz wants to move toward always using > > the parens, at least on any inner call. Once that's done, it seems > > like non-comma notation might be possible. > > > >> But I don't know if both means of specifying arguments can be combined > >> harmoniously. It's something I need to think about some more. > > > > Me too. Edge cases are often difficult to phathom. > > Well, let's see. I think this would be ambiguous if both "m a, b, c" and > "m(a b c)" is allowed: > > m(a b) > > If we don't allow parentheses in one argument methods, I think we are safe > because then there's always a comma. However it is not so easy to parse > things (for a computer as well as for a human): > > m(a b,c,d) > > So "a b" cannot be interpreted as a method call by itself because of the > one argument rule, and thus the proper interpretation can only be this: > > m(a(b,c,d)) > > But see how I need to reason about this to find this out? > > But this means that "puts something" is no longer valid. The problem isn't > the bracketed form, it's the comma form. I think it's the lack of > punctuation between the method name and the first parameter that is the > problem. For one thing that means there's no punctuation when there's just > one parameter. > > Ah, but wait, there's still a problem: > > a b,c d,e,f > > Is this > > a(b, c(d,e), f) > > or > > a(b, c(d,e,f)) > > ? Of course as with lambda calculus we can say that a subexpression is > taken as long as possible. That would work, as it disambiguates things in > general. I don't know if that is good though, I know from personal > experience with bachelor students that this is a very hard rule. I was thinking that in the future only mathods starting a new line (or after a semi-colon) could forgo the parens. So irb(main):003:0> a b 1 (irb):3: warning: parenthesize argument(s) for future version => 1 irb(main):005:0> a( b 1 ) (irb):5: warning: parenthesize argument(s) for future version => 1 but irb(main):004:0> a b( 1 ) => 1 So "m(a b)" isn't allowed. It would have to be one of the two: m(a(b)) or m(a,b) That's seems to leave the door open for m(a b) === m(a,b) I'm trying to think of a case were there is an ambiguity and no reasonabe default interpretation --or no way to use parens to disambiguate b/c it causes further ambiguity, but I can't yet think of one. T.