*WHY* does this not work?

ok, so code:

str = ‘foo’
=> “foo”
str.each_char do |c|
c = ‘x’
end
=> “foo”

WHY does str == ‘foo’ still?? i would expect it to be ‘xxx’! this makes
no
sense, and is QUITE annoying… i end up having to do things like
this:

… i CAN’T do things like that for a string because it dsn’t seem to do
that, but for an array i’d have to:

ary = [‘f’, ‘o’, ‘o’]
=> [“f”, “o”, “o”]
ary.each_index do |i|
ary[i] = ‘x’
end
=> [“x”, “x”, “x”]

GAH!!! least surprise?? least surprise my FOOT!!! even if there was a
*.each! method to do that i would be fine, that would be ok, none of
this
'get the index and then do what you need to do and THEN set the stupid
block variable… GRRRRRR!!!

/vent
hex


my blog is cooler than yours: serialhex.github.com

The wise man said: “Never argue with an idiot. They bring you down to
their
level and beat you with experience.”

Other than the fact Linux has a cool name, could someone explain why I
should use Linux over BSD?

No. That’s it. The cool name, that is. We worked very hard on
creating a name that would appeal to the majority of people, and it
certainly paid off: thousands of people are using linux just to be able
to say “OS/2? Hah. I’ve got Linux. What a cool name”. 386BSD made the
mistake of putting a lot of numbers and weird abbreviations into the
name, and is scaring away a lot of people just because it sounds too
technical.
– Linus Torvalds’ follow-up to a question about Linux

On Tue, Aug 9, 2011 at 3:05 PM, Darryl L. Pierce [email protected]
wrote:

WHY does str == ‘foo’ still??

Because each_char is not destructive to the original string’s value. It
moves through the string as an array of characters and then passes each
one by value to the block supplied. So while you might be able to
locally alter the value for that character, you don’t have access to the
original string itself in the block.

so is there a way to do that? easily without jumping through hoops of
fire??

Sometimes it’s your expectation that’s wrong and not the library you’re
using. :wink:

true, oh how annoyingly true… :stuck_out_tongue:
hex


my blog is cooler than yours: serialhex.github.com

The wise man said: “Never argue with an idiot. They bring you down to
their
level and beat you with experience.”

Other than the fact Linux has a cool name, could someone explain why I
should use Linux over BSD?

No. That’s it. The cool name, that is. We worked very hard on
creating a name that would appeal to the majority of people, and it
certainly paid off: thousands of people are using linux just to be able
to say “OS/2? Hah. I’ve got Linux. What a cool name”. 386BSD made the
mistake of putting a lot of numbers and weird abbreviations into the
name, and is scaring away a lot of people just because it sounds too
technical.
– Linus Torvalds’ follow-up to a question about Linux

On Tue, Aug 9, 2011 at 9:11 PM, serialhex [email protected] wrote:

so is there a way to do that? easily without jumping through hoops of
fire??

str.gsub(/./,“x”) # :stuck_out_tongue:
=> “xxx”


Phillip G.

phgaw.posterous.com | twitter.com/phgaw | gplus.to/phgaw

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibniz

On Tue, Aug 9, 2011 at 1:52 PM, serialhex [email protected] wrote:

sense, and is QUITE annoying… i end up having to do things like this:

There are two reasons.

  1. c is a variable. When you say c = 'x', you are updating the
    object
    that the variable c is pointing to, not invoking some sort of setter on
    the
    string you are iterating over (which is what you are doing in the
    array
    example when you invoke the #[]= method).

  2. Even if you were able to actually change the string, ie using
    c.replace 'x' rather than c = x, it wouldn’t matter, because the char that c
    is
    pointing to is a completely different string than str.

I don’t know what you’re trying to do, so I can’t suggest a better
solution,
but there is a way to do what you are asking using String#gsub!
str = “abc”
str.gsub!(/./) { |char| ‘x’ }
str # => “xxx”

GAH!!! least surprise?? least surprise my FOOT!!! even if there was a
*.each! method to do that i would be fine, that would be ok, none of this
'get the index and then do what you need to do and THEN set the stupid
block variable… GRRRRRR!!!

Try Array#map!

ary = [‘f’, ‘o’, ‘o’]
ary.map! { |char| ‘x’ }
ary # => [“x”, “x”, “x”]

On Wed, Aug 10, 2011 at 03:52:59AM +0900, serialhex wrote:

ok, so code:

str = ‘foo’
=> “foo”
str.each_char do |c|
c = ‘x’
end
=> “foo”

WHY does str == ‘foo’ still??

Because each_char is not destructive to the original string’s value. It
moves through the string as an array of characters and then passes each
one by value to the block supplied. So while you might be able to
locally alter the value for that character, you don’t have access to the
original string itself in the block.

i would expect it to be ‘xxx’! this makes no
sense, and is QUITE annoying…

If you look at the source code for each_char you’ll see that its return
value is the original string itself. Which is why you see “foo”
returned.

Sometimes it’s your expectation that’s wrong and not the library you’re
using. :wink:

On Wed, Aug 10, 2011 at 04:11:05AM +0900, serialhex wrote:

=> “foo”
fire??
You want to iterate through a string and change individual characters?
Why not just do:

str = “farkle”
(0…str.size).each {|index| str[index] = ‘x’}

On Wed, Aug 10, 2011 at 03:52:59AM +0900, serialhex wrote:

ok, so code:

str = ‘foo’
=> “foo”
str.each_char do |c|
c = ‘x’
end
=> “foo”

Try this:

str.gsub!(/\w/, 'x')

WHY does str == ‘foo’ still?? i would expect it to be ‘xxx’!

The common way to handle things in Ruby is to not change the receiver
of a message. To do otherwise is surprising.

… i CAN’T do things like that for a string because it dsn’t seem to do
that, but for an array i’d have to:

ary = [‘f’, ‘o’, ‘o’]
=> [“f”, “o”, “o”]
ary.each_index do |i|
ary[i] = ‘x’
end
=> [“x”, “x”, “x”]

. . . or use a map:

ary.map! {|element| element.sub /\w/, 'x' }

GAH!!! least surprise?? least surprise my FOOT!!! even if there was a
*.each! method to do that i would be fine, that would be ok, none of this
'get the index and then do what you need to do and THEN set the stupid
block variable… GRRRRRR!!!

You’re operating on c, not on str. It would be more surprising if when
operating on c it changed str, in my opinion.

The each method is an iterator – not an editor. If you want to map an
operation onto an array, you should use the map method. If you want to
do substitutions on characters in a string, use a substitution method.
What could be less surprising than using the right tool for the job?

I think you’re surprised because you expect one tool to do everything.
I would be pretty surprised if someone could make such a tool that
wasn’t
bad at everything it did.

Morning,

On Tue, Aug 9, 2011 at 12:11 PM, serialhex [email protected] wrote:

On Tue, Aug 9, 2011 at 3:05 PM, Darryl L. Pierce [email protected]
wrote:

so is there a way to do that? easily without jumping through hoops of
fire??

Maybe something like this would be of help

str.length.times do |i|
str[i] = ‘x’
end

John

ok, many responses, all very good and reasonable, but i guess my point
is
kinda missed so i’ll explain deeper…

here is an awesome kludge of a program i wrote last night:

yes it’s ugly, and yes it’s horrible, but it’s not meant to be used for
anything more than what it was used for (which is quickly converting
python
to ruby, and give kinda workable results most of the time, and since
it’s
simply single file programs that i was going to edit & fix later, i’m
not
worried as to how ugly the translator is, or the translation, it just
did
90% of my work for me)

look at the strip_python_loads method, that is the best way i can come
up
with at the moment. yes i know there are better ways (to write this and
the
entire program) but what are they? if i wanted to edit the contents of
an
array while iterating through it how do it do it besides that? like i
said,
a method such as each! which will allow you to modify the receiver would
be
nice…
hex

p.s. oh, and if you want to fork & edit that gist to make it prettier &
more
useful feel free to do so!


my blog is cooler than yours: serialhex.github.com

The wise man said: “Never argue with an idiot. They bring you down to
their
level and beat you with experience.”

Other than the fact Linux has a cool name, could someone explain why I
should use Linux over BSD?

No. That’s it. The cool name, that is. We worked very hard on
creating a name that would appeal to the majority of people, and it
certainly paid off: thousands of people are using linux just to be able
to say “OS/2? Hah. I’ve got Linux. What a cool name”. 386BSD made the
mistake of putting a lot of numbers and weird abbreviations into the
name, and is scaring away a lot of people just because it sounds too
technical.
– Linus Torvalds’ follow-up to a question about Linux

On Tue, Aug 9, 2011 at 1:11 PM, serialhex [email protected] wrote:

so is there a way to do that? easily without jumping through hoops of
fire??

How I’d do it:
std.length.times { |i| str[i] = ‘x’ }

-Jonathan N.

On Tue, Aug 9, 2011 at 2:38 PM, serialhex [email protected] wrote:

It has been pointed out several times that Array#map! does this.

In your case, though, it looks like you’d prefer Array#reject!

def strip_python_loads
@file_lines.reject! { |line| line =~ /\sfrom[
A-Za-z0-9_.]import\s\w
/
}
end

On Wed, Aug 10, 2011 at 04:49:13AM +0900, Josh C. wrote:

It has been pointed out several times that Array#map! does this.

In your case, though, it looks like you’d prefer Array#reject!

def strip_python_loads
@file_lines.reject! { |line| line =~ /\sfrom[ A-Za-z0-9_.]import\s\w/
}
end

I should have thought of that. I’d probably use do . . . end rather
than
braces for that, though. The line’s just too long to be comfortable
this
way.

On Wed, Aug 10, 2011 at 04:38:36AM +0900, serialhex wrote:

worried as to how ugly the translator is, or the translation, it just did
90% of my work for me)

look at the strip_python_loads method, that is the best way i can come up
with at the moment. yes i know there are better ways (to write this and the
entire program) but what are they? if i wanted to edit the contents of an
array while iterating through it how do it do it besides that? like i said,
a method such as each! which will allow you to modify the receiver would be
nice…

def strip_python_loads
  @file_lines.map! do |line|
    line = '' if line.match(/\s*from[ A-Za-z0-9\_.]*import\s*\w*/])
    line
  end
end

Warning: I have not tested this code. I may have made a boneheaded
error. There may also be a better way to do this that would have
occurred to me if I was not multitasking.

On Tue, Aug 9, 2011 at 3:49 PM, Josh C. [email protected] wrote:

It has been pointed out several times that Array#map! does this.

In your case, though, it looks like you’d prefer Array#reject!

def strip_python_loads
@file_lines.reject! { |line| line =~ /\sfrom[ A-Za-z0-9_.]import\s\w/
}
end

hmm… i guess i’m gonna have to delve deeper into some of the array &
string docs deeper
hex


my blog is cooler than yours: serialhex.github.com

The wise man said: “Never argue with an idiot. They bring you down to
their
level and beat you with experience.”

Other than the fact Linux has a cool name, could someone explain why I
should use Linux over BSD?

No. That’s it. The cool name, that is. We worked very hard on
creating a name that would appeal to the majority of people, and it
certainly paid off: thousands of people are using linux just to be able
to say “OS/2? Hah. I’ve got Linux. What a cool name”. 386BSD made the
mistake of putting a lot of numbers and weird abbreviations into the
name, and is scaring away a lot of people just because it sounds too
technical.
– Linus Torvalds’ follow-up to a question about Linux

c represents a temporary variable with a copy of the char in it. This is
always the case. Use the map and join methods if you want to construct a
new string in that manner, and then set the variable pointing to the old
string to the new string.

Blog: http://random8.zenunit.com/
Twitter: http://twitter.com/random8r
Learn: http://sensei.zenunit.com/
New video up now at http://sensei.zenunit.com/
real fastcgi rails deploy process! Check it out now!

It depends on two things: whether you want to preserve the input lines
or not.

First of all, I would do such stuff in a function that takes an
argument. It keeps
you from being dependent on an instance variable. So I will use:

def strip_python_loads(input)

This makes the code usable in more contexts.

Now, if you don’t care about preserving line numbers, you can do the
following:

text = <<PYTHON
from foo import bar

batz
PYTHON

def strip_python_loads(input)
  input.reject { |line| line =~ /\s*from[ 

A-Za-z0-9_.]import\s\w*/ }
# or reject! if you want to destruct input
end

puts strip_python_loads(text.split("\n")).join("\n")

Preserving input can be done using #map:

text = <<PYTHON
from foo import bar

batz
PYTHON

def strip_python_loads(input)
  input.map do |line|
    unless line =~ /\s*from[ A-Za-z0-9\_.]*import\s*\w*/
      line
    end
  end
  #same here, #map! works destructively
end

puts strip_python_loads(text.split("\n")).join("\n")
# or even
puts strip_python_loads(text.lines).join("\n")

Regards,
Florian

On Aug 9, 2011, at 9:38 PM, serialhex wrote:

worried as to how ugly the translator is, or the translation, it just did
p.s. oh, and if you want to fork & edit that gist to make it prettier & more

should use Linux over BSD?

No. That’s it. The cool name, that is. We worked very hard on
creating a name that would appeal to the majority of people, and it
certainly paid off: thousands of people are using linux just to be able
to say “OS/2? Hah. I’ve got Linux. What a cool name”. 386BSD made the
mistake of putting a lot of numbers and weird abbreviations into the
name, and is scaring away a lot of people just because it sounds too
technical.
– Linus Torvalds’ follow-up to a question about Linux


Florian G.

smtp: [email protected]
jabber: [email protected]
gpg: 533148E2

Or use each_eith_index which is a bit nicer rather than constructing a
range.

Blog: http://random8.zenunit.com/
Twitter: http://twitter.com/random8r
Learn: http://sensei.zenunit.com/
New video up now at http://sensei.zenunit.com/
real fastcgi rails deploy process! Check it out now!

Whilst Ruby is probably a perfectly logical and self-consistent language
I personally think it has no right whatsoever to claim least surprise.

I’ve always said Matz finds Ruby unsurprising, but that’s because he
wrote it.

Editing the contents of an array while you’re iterating it is generally
considered bad programming practice… Because if you delete things,
indexing becomes unpredictable. Using copies of arrays is usually a
better practice generally.

Blog: http://random8.zenunit.com/
Twitter: http://twitter.com/random8r
Learn: http://sensei.zenunit.com/
New video up now at http://sensei.zenunit.com/
real fastcgi rails deploy process! Check it out now!

If you want to replace or strip things from strings, use those methods.
Don’t recreate the wheel. I suggest you look into the string class’s
methods fairly deeply.

Blog: http://random8.zenunit.com/
Twitter: http://twitter.com/random8r
Learn: http://sensei.zenunit.com/
New video up now at http://sensei.zenunit.com/
real fastcgi rails deploy process! Check it out now!