Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Alter String base class to perform new (private methods) beforereturning itself when called by print statements

Reply
Thread Tools

Alter String base class to perform new (private methods) beforereturning itself when called by print statements

 
 
Steven G. Harms
Guest
Posts: n/a
 
      02-16-2008
class String
def summon
puts "You summon: " + self
end
def summon2
puts "You summon: " + self.gsub('x','y')
end
def to_s
return "Atreyu"
end
end

"Artax".summon
"Artax".summon2

puts "Artax".to_s # reference 1
puts "Artax" # reference 2

This produces...

You summon: Artax
You summon: Artay
Atreyu
Artax

Now the "summon" methods indicate to me that by referencing self in
methods added to the String class, you can alter the string from
within itself. The question is, how can I get `puts "Artax" ` to
produce the same results as `puts "Artax"`. They are both Strings
and, as far as I understand it, to_s is what is used to get a String's
display value.

Question #1: Is there a way to references 1 and 2, supra, to do the
same thing?

Question #2: I thought perhaps I could do the magic on the assignment
operation. I'm not having too much luck with that, as yet.

If this is the best solution, could the responding individual please
be so gracious as to provide example code of how to override
assignment? I'm muddling about with my re-defined initialize
expecting an optional argument, but I've not figured out how to access
it properly.

Thanks,

Steven




 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      02-16-2008
On 16.02.2008 07:26, Steven G. Harms wrote:
> class String
> def summon
> puts "You summon: " + self
> end
> def summon2
> puts "You summon: " + self.gsub('x','y')
> end
> def to_s
> return "Atreyu"
> end
> end
>
> "Artax".summon
> "Artax".summon2
>
> puts "Artax".to_s # reference 1
> puts "Artax" # reference 2
>
> This produces...
>
> You summon: Artax
> You summon: Artay
> Atreyu
> Artax
>
> Now the "summon" methods indicate to me that by referencing self in
> methods added to the String class, you can alter the string from
> within itself.


Actually your summon methods do not alter self.

> The question is, how can I get `puts "Artax" ` to
> produce the same results as `puts "Artax"`.


??? It's the same statement so I would expect the same output (module
changes of the instance in between invocations).

> They are both Strings
> and, as far as I understand it, to_s is what is used to get a String's
> display value.


It's generally not a good idea to mess with such basic classes like
String in this way (i.e. make to_s return something else than self).
Since your example does not contain context it's difficult to come up
with appropriate suggestions. What are you *really* trying to achieve?

> Question #1: Is there a way to references 1 and 2, supra, to do the
> same thing?


Not sure what you mean here. Can you explain?

> Question #2: I thought perhaps I could do the magic on the assignment
> operation. I'm not having too much luck with that, as yet.


You cannot change the semantics of assignment. You can however define
methods that look like assignment, i.e. def foo=(x)...end. I doubt
though that this is helpful for you in this context.

> If this is the best solution, could the responding individual please
> be so gracious as to provide example code of how to override
> assignment? I'm muddling about with my re-defined initialize
> expecting an optional argument, but I've not figured out how to access
> it properly.


Again, what problem are you trying to solve?

Kind regards

robert
 
Reply With Quote
 
 
 
 
Todd Benson
Guest
Posts: n/a
 
      02-16-2008
On Feb 16, 2008 12:29 AM, Steven G. Harms <(E-Mail Removed)> wrote:
> class String
> def summon
> puts "You summon: " + self
> end
> def summon2
> puts "You summon: " + self.gsub('x','y')
> end


Keep in mind that these methods output what you want in irb, but
return nil. In my irb session it looks something like this...
irb(main):001:0> class String
irb(main):002:1> def summon
irb(main):003:2> puts "You summon: " + self
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> s = "hello".summon
You summon: hello
=> nil
irb(main):007:0> s
=> nil

> def to_s
> return "Atreyu"
> end
> end
>
> "Artax".summon
> "Artax".summon2
>
> puts "Artax".to_s # reference 1
> puts "Artax" # reference 2
>
> This produces...
>
> You summon: Artax
> You summon: Artay
> Atreyu
> Artax
>
> Now the "summon" methods indicate to me that by referencing self in
> methods added to the String class, you can alter the string from
> within itself.


Yes, this is possible.

> The question is, how can I get `puts "Artax" ` to
> produce the same results as `puts "Artax"`. They are both Strings
> and, as far as I understand it, to_s is what is used to get a String's
> display value.
>
> Question #1: Is there a way to references 1 and 2, supra, to do the
> same thing?


Look at these two (using the previous code)...

puts s.to_s
puts(s).to_s

>
> Thanks,
>
> Steven


Todd

 
Reply With Quote
 
Todd Benson
Guest
Posts: n/a
 
      02-16-2008
On Feb 16, 2008 7:37 AM, Todd Benson <(E-Mail Removed)> wrote:
> Look at these two (using the previous code)...
>
> puts s.to_s
> puts(s).to_s


No, no , no!! Not using all the previous code! My bad. More "after"
code for you (BTW, Robert's right, you shouldn't really mess with
#to_s)...

class String
def to_s
"hi"
end
end

puts "hello".to_s
puts("hello").to_s

Todd

 
Reply With Quote
 
Steven G. Harms
Guest
Posts: n/a
 
      02-16-2008
Robert, Todd, et. al.,

I apologize if my first post was missing some of the larger context, I
didn't want to have to give too much information about the problem
domain lest that deter replies .

The code I'm working on is used for storing Strings which contain
conjugations of Latin verbs ( I mean, people who lived near the
Mediterranean, not people south of the Rio Grande ).

Classical Latin words contain macrons on certain vowels ( the long bar
that signifies a "long" sound ). When following conjugation rules
occasionally the "macron-ized" character needs to be "shortened" and
the macron thus removed. Thus, for example "they love" is the stem of
the infinitive remove_ending("am\={a}re") + "nt" (I'm using LaTeX
style macron representation).

The rules dictate that you should chop off the "re" and add the "nt",
thus giving you "am\={a}nt".

BUT here's the rule, a macronized vowel before 'nt' or 'nd' anywhere
in the string must be shortened, thus the word is *actually* "amant".
There are other conditions that shorten a macron (comes before another
vowel, etc.).

Here's the output (at top) and code (at bottom): http://stevengharms.com/?page_id=1159

While I have the code that produces the "right" output, I'm trying to
refactor the code to be more Ruby-like, cleaner, and more organized.
So the code that I link to here is still functional, but not final
draft!

As it is currently, you enter a verb characterization from the CLI, a
Verb.new object is created with that string as the input. Those
pieces are broken up and you have a Verb object. You can then issue:

demo_verb=Verb.new( verb characterization string )
puts demo_verb.active_present

In 'active_present" 6 strings are created and returned in an array.
Each of these strings are passed to a "check_macron" routine which
removes macrons where needed.

Point #1 ( Original Question, effectively)

My idea was "Well, what if *every* string, in the duration of this
program, knows to check_macron itself at time of assignment OR at time
of being used for output" -- my idea being to "smarten" up String so
that I didn't have to go around invoking check_macron all over the
place. Further, I wouldn't have to change my ( heavy! ) use of the
String assignment idioms ( heavily used ).

Point #2:

I was against the idea of subclassing String because, as i understand
it, my assignments would take the look of:

aLatinString = LatinString.new("something")

instead of the very short and pleasant:

aRegularString = "razzle"

Perhaps I am mistaken in this?

Well, so that's the full story, likely full of a lot of extra details,
but hopefully you will make it through and be able to guide me to more
Ruby like constructions!

Steven




 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      02-17-2008
On 16.02.2008 18:10, Steven G. Harms wrote:
> Robert, Todd, et. al.,
>
> I apologize if my first post was missing some of the larger context, I
> didn't want to have to give too much information about the problem
> domain lest that deter replies .


No problem at all. Sometimes it's hard to see where one should draw the
line between too much and too few information to help people understand
what's going on.

> The code I'm working on is used for storing Strings which contain
> conjugations of Latin verbs ( I mean, people who lived near the
> Mediterranean, not people south of the Rio Grande ).


My Latin is very rusty nowadays but this brings back memories (our
first sentence in class five was "agricola arat")...

> Classical Latin words contain macrons on certain vowels ( the long bar
> that signifies a "long" sound ). When following conjugation rules
> occasionally the "macron-ized" character needs to be "shortened" and
> the macron thus removed. Thus, for example "they love" is the stem of
> the infinitive remove_ending("am\={a}re") + "nt" (I'm using LaTeX
> style macron representation).
>
> The rules dictate that you should chop off the "re" and add the "nt",
> thus giving you "am\={a}nt".
>
> BUT here's the rule, a macronized vowel before 'nt' or 'nd' anywhere
> in the string must be shortened, thus the word is *actually* "amant".
> There are other conditions that shorten a macron (comes before another
> vowel, etc.).
>
> Here's the output (at top) and code (at bottom): http://stevengharms.com/?page_id=1159


Where exactly? I could neither see code nor latin words on that page.

> While I have the code that produces the "right" output, I'm trying to
> refactor the code to be more Ruby-like, cleaner, and more organized.
> So the code that I link to here is still functional, but not final
> draft!
>
> As it is currently, you enter a verb characterization from the CLI, a
> Verb.new object is created with that string as the input. Those
> pieces are broken up and you have a Verb object. You can then issue:
>
> demo_verb=Verb.new( verb characterization string )
> puts demo_verb.active_present
>
> In 'active_present" 6 strings are created and returned in an array.
> Each of these strings are passed to a "check_macron" routine which
> removes macrons where needed.


Personally I find this naming a bit unfortunate: checking is usually a
read only operation while you are actually manipulating something.

> Point #1 ( Original Question, effectively)
>
> My idea was "Well, what if *every* string, in the duration of this
> program, knows to check_macron itself at time of assignment OR at time
> of being used for output" -- my idea being to "smarten" up String so
> that I didn't have to go around invoking check_macron all over the
> place. Further, I wouldn't have to change my ( heavy! ) use of the
> String assignment idioms ( heavily used ).


That's double "heavy" - man this must be really heavy.

I can see where your motivation comes from. Generally I'd opt for not
putting this into class String because it is too specialized (i.e
functionality that does make sense in context of your application only).

One possible solution that might not too bad from your point of view:
add a class and define a conversion method, e.g.

LatinString = Struct.new :string do
def remove_macron
...
end

def to_s
# for printing...
end
end

class String
def to_latin
LatinString.new self
end
end

now you can do

die = "alea".to_latin

Another alternative (modifying assignment) could be this:

class LatinVocabulary
def initialize
@vars = {}
end

def method_missing(sym, *args, &b)
name = sym.to_s

case
when /^(.*)=$/ =~ name && args.length == 1
# assignment
@vars[$1] = remove_macron(args.first)
when args.empty? && @vars.has_key? name
# getter
@vars[name]
else
super
end
end

def remove_macron(str)
...
end
end

And then

voc = LatinVocabulary.new
voc.die = "alea"
voc.peasant = "agricola"

> Point #2:
>
> I was against the idea of subclassing String because, as i understand
> it, my assignments would take the look of:
>
> aLatinString = LatinString.new("something")
>
> instead of the very short and pleasant:
>
> aRegularString = "razzle"
>
> Perhaps I am mistaken in this?


No, you are not. How should the interpreter know that "..." suddenly
creates a LatinString and not a String? This is really hard coded into
the language. And it's good that way because otherwise all sorts of
nasty things could happen if anybody could change this.

> Well, so that's the full story, likely full of a lot of extra details,
> but hopefully you will make it through and be able to guide me to more
> Ruby like constructions!


I am still a bit unsure about when those conversions need to be done
because I did not find the code where you indicated. From what you
write method Verb#active_present generates this list you mentioned.
Now, should this list be a list of plain Strings or do you need
LatinStrings to be returned, i.e. does the result of this method call
have to be modified already or do you need to be able to do it later?
If the former, then you can apply the conversion in Verb#active_present,
if the latter you can return a LatinString (as shown above).

But generally, if you need a String with particular properties, create
your own class for this. There are enough options to make handling and
printing of anything as convenient as printing Strings. My 0.03EUR...

Kind regards

robert
 
Reply With Quote
 
Steven G. Harms
Guest
Posts: n/a
 
      02-17-2008
Robert,

Thank you for such a connsidered reply.

On Feb 17, 4:57*am, Robert Klemme <(E-Mail Removed)> wrote:
> *My Latin is very rusty nowadays but this brings back memories (our
> first sentence in class five was "agricola arat")...


It's always about the farmers, isn't it?

> > Here's the output (at top) and code (at bottom):http://stevengharms.com/?page_id=1159

>
> Where exactly? I could neither see code nor latin words on that page.


I *believe* you can now see the code at:
http://stevengharms.com/improving-th...erb-conjugator

I just changed my 'slug' type and failed to understand that the
preview was for admin-eyes-only.

> > In 'active_present" 6 strings are created and returned in an array.
> > Each of these strings are passed to a "check_macron" routine which
> > removes macrons where needed.

>
> Personally I find this naming a bit unfortunate: checking is usually a
> read only operation while you are actually manipulating something.

I see your point on check_macron not being optimally named, let me
keep the old name for purposes of this thread but I'll act on that
recommendation.

> I can see where your motivation comes from. *Generally I'd opt for not
> putting this into class String because it is too specialized (i.e
> functionality that does make sense in context of your application only).

[ code snip ]

That's sensible. I've never seen this Struct.new syntax so I'll be
eager to try it out. I think i ( perhaps cumbersomely? ) wind up
going more-or-less along this design pattern ( now that you can see
the code ).


> Another alternative (modifying assignment) could be this:
>
> class LatinVocabulary
> * *def initialize
> * * *@vars = {}
> * *end
>
> * *def method_missing(sym, *args, &b)
> * * *name = sym.to_s
>
> * * *case
> * * *when /^(.*)=$/ =~ name && args.length == 1
> * * * *# assignment
> * * * *@vars[$1] = remove_macron(args.first)
> * * *when args.empty? && @vars.has_key? name
> * * * *# getter
> * * * *@vars[name]
> * * *else
> * * * *super
> * * *end
> * *end
>
> * *def remove_macron(str)
> * * *...
> * *end
> end
>
> And then
>
> voc = LatinVocabulary.new
> voc.die = "alea"
> voc.peasant = "agricola"


This feels very "intro to metaprogramming" - the use of the
method_missing method could, in principle, be used to expand the
class. i.e.(pseudocode) "if method_missing (:active_present) do the
active_present build with macron_sanitization routine". This may be
where my code goes to once I get a bit more cleaned up.

> > instead of the very short and pleasant:

>
> > aRegularString = "razzle"

>
> > Perhaps I am mistaken in this?

>
> No, you are not. *How should the interpreter know that "..." suddenly
> creates a LatinString and not a String? *This is really hard coded into
> the language. *And it's good that way because otherwise all sorts of
> nasty things could happen if anybody could change this.


Heh, well I suppose I was a bit overwhelmed by the idea of open
classes and figured that Ruby would let me saw my hand off on this
point, if I wanted to. That said, I agree it's probably a good thing
that this can't get mucked about with.

> LatinStrings to be returned, i.e. does the result of this method call
> have to be modified already or do you need to be able to do it later?
> If the former, then you can apply the conversion in Verb#active_present,
> if the latter you can return a LatinString (as shown above).


I think I wind up doing the former

Thank you for your illuminating replies,

Steven

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      02-17-2008
On 17.02.2008 15:00, Steven G. Harms wrote:
> Thank you for such a connsidered reply.


You're welcome!

> On Feb 17, 4:57 am, Robert Klemme <(E-Mail Removed)> wrote:
>> My Latin is very rusty nowadays but this brings back memories (our
>> first sentence in class five was "agricola arat")...

>
> It's always about the farmers, isn't it?


)

>>> Here's the output (at top) and code (at bottom):http://stevengharms.com/?page_id=1159

>> Where exactly? I could neither see code nor latin words on that page.

>
> I *believe* you can now see the code at:
> http://stevengharms.com/improving-th...erb-conjugator


I can confirm that.

Few remarks: your type checking can be simplified:

case input
when Array
....
when String
....
else
raise ArgumentError, "wrong type: #{input.inspect}"
end

Same for the conjugation, for which I would introduce symbols as names
(not "1", "2" etc.).

Same in evaluate_conjugation.

def evaluate_conjugation
case @infinitive
when /\?re$/ # what exactly should your regexp look like?
# question mark without escaping backslash
# is not so good
"1" # or rather a symbol denoting the name
when /...
...
else
end
end


>> I can see where your motivation comes from. Generally I'd opt for not
>> putting this into class String because it is too specialized (i.e
>> functionality that does make sense in context of your application only).

> [ code snip ]
>
> That's sensible. I've never seen this Struct.new syntax so I'll be
> eager to try it out. I think i ( perhaps cumbersomely? ) wind up
> going more-or-less along this design pattern ( now that you can see
> the code ).


Struct.new is actually just a convenient way to create a new class with
a set of properties that are honored during #hash, #eql? and #== so
instances can be easily compared and used as Hash keys.

[...]

> This feels very "intro to metaprogramming" - the use of the
> method_missing method could, in principle, be used to expand the
> class. i.e.(pseudocode) "if method_missing (:active_present) do the
> active_present build with macron_sanitization routine". This may be
> where my code goes to once I get a bit more cleaned up.


If you know the method beforehand it is more efficient to define it
right away.

>> LatinStrings to be returned, i.e. does the result of this method call
>> have to be modified already or do you need to be able to do it later?
>> If the former, then you can apply the conversion in Verb#active_present,
>> if the latter you can return a LatinString (as shown above).

>
> I think I wind up doing the former
>
> Thank you for your illuminating replies,


You're welcome! I'm glad I could help.

Kind regards

robert
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Base class parameters called on Derived class: behaviour Nagrik C++ 3 11-28-2007 09:09 PM
Alter - Perl extension for Alter Ego Objects anno4000@radom.zrz.tu-berlin.de Perl Misc 0 06-30-2007 04:13 PM
Alter base target through asp.net code frichard@nospam.com ASP .Net 0 03-18-2006 08:28 AM
Access of base class' private base class: qualification required, why Alf P. Steinbach C++ 6 09-03-2005 04:03 PM
in VB.NET Page_load of a base class called after the derived class Page_load ? z. f. ASP .Net 0 10-19-2004 12:01 PM



Advertisments