undefine

S

Sean O'Dell

while(<binkd>)
{
# date parsing code was here
@diff=Delta_DHMS(@binkdate,@today) if /(\[\d+\])/;
print $trimmed $_ if $diff[0] < $ARGV[1] && defined(@diff);
next if defined(@diff);
print $trimmed $_ if ! /(\[\d+\])/;
undef(@diff);
}

testing whether diff is defined won't work in ruby anyway. Any time you
have an expression like this:

foo = 23 if expression

foo ends up being automagically defined anyway. After running that
code, if expression is false, foo == nil.

So, as Sean says, it would probably be better to use nil, unless
Delta_DHMS might return nil itself.

Oh! Which brings to mind something really neat I figured out awhile ago. If
Delta_DHMS really can return nil as a valid value, try re-writing the code
like this:

{
# date parsing code was here
@diff=Delta_DHMS(@binkdate,@today) if /(\[\d+\])/;
print $trimmed $_ if $diff[0] < $ARGV[1] && @diff != :undefined;
next if @diff != :undefined;
print $trimmed $_ if ! /(\[\d+\])/;
@diff = :undefined;
}

Initialize @diff = :undefined in your class initialize method. :undefined
will be a Ruby symbol that gets created on its first use. From there on out,
just set @diff to :undefined whenever you need to "undefine" it.

Sean O'Dell
 
T

tony summerfelt

Can't you just use "=nil" to achive the same thing?
(just using the fact that 'nil' is false)

in perl it's null. which is what defined() and undef() test for...
 
T

tony summerfelt

testing whether diff is defined won't work in ruby anyway. Any time you
have an expression like this:
foo = 23 if expression
foo ends up being automagically defined anyway. After running that
code, if expression is false, foo == nil.

yeah, like i said undef would be great :)
So, as Sean says, it would probably be better to use nil, unless
Delta_DHMS might return nil itself.

that was just one method from an external perl module, and i when
successful returns an array...not sure if it can return a null or
not...either way it's just as easy to use defined/undef in perl...
 
J

Josh Huber

tony summerfelt said:
in perl it's null. which is what defined() and undef() test
for...

I'm aware what they do, but you can get the desired behavior
using nil. I mean, you're trying to use Ruby, not Perl right?
 
M

Mark Sparshatt

tony said:
What about the logic of your code or design depends on the 'existence'
of a variable? What problem is it you're trying to solve with this
approach?

just makes the code shorter. here's an excerpt of a log trimming
program in perl (for the format that binkd generates) ('@' precedes
arrays in perl):

while(<binkd>)
{
# date parsing code was here
@diff=Delta_DHMS(@binkdate,@today) if /(\[\d+\])/;
print $trimmed $_ if $diff[0] < $ARGV[1] && defined(@diff);
Here you check that @diff is defined after trying to access an element
of diff, is that right?
next if defined(@diff);
print $trimmed $_ if ! /(\[\d+\])/;
undef(@diff);
}
How about this (untested)?

while(binkd)
# date parsing code was here
diff=Delta_DHMS(binkdate, today) if /(\[\d+\])/
print $trimmed $_ if diff && diff[0] < ARGV[1]
next if diff
print $trimmed $_ if ! /(\[\d\])/
diff = nill
end
 
J

Jean-Hugues ROBERT

Robert Klemme wrote:
.....


I did not advocate removing, a.k.a. undefining,
instance variable, I was just pointing out that
these removal methods exists - but since you asked:

Removing an instance or class variable after
its usefulness expired (a typical example are
auxiliary instance variable used in nontrivial
initializers distributed over several auxiliary
methods) is IMO a good practice mainly for
esthetical reasons (akin to the well established
practice of always initialing instance variable
before using them) - on occasion you might even
catch an error this way. Another reason is that
unused instance variable take up unnecessary
memory space.

It seems harder to me to make a similar compelling
stylistic (and memory) case for the existence of
removal methods for class variables and especially
for global variables, and removal method for local
variables make no sense at all.

/Christoph

OTOH things should be undoable. If you believe so
then undefining a local variable (or whatever can
be defined) makes *some* sense. I must confess that
how to use such an undefine action in a clean way
is something I have yet to figure out ;-)

BTW: defined?() tells you about whether a variable
is defined, including local ones.

Yours,

JeanHuguesRobert
 
R

Robert Klemme

tony summerfelt said:
it seems to be more work (and lines of code) than it needs to be for
just one variable.

i was surprised that ruby didn't have a simple undefine function. and
for the oo'ness of it, it could look like x.undefine. no more x :)

It can't, because "x" and the object pointed at by it (and which thus
receives method invocations) are two different things. The instance
referenced by "x" does not know anything about the context's local binding
of "x"; especially it does not know that the method was invoked through a
reference named "x".

robert
 
R

Robert Klemme

Sean O'Dell said:
while(<binkd>)
{
# date parsing code was here
@diff=Delta_DHMS(@binkdate,@today) if /(\[\d+\])/;
print $trimmed $_ if $diff[0] < $ARGV[1] && defined(@diff);
next if defined(@diff);
print $trimmed $_ if ! /(\[\d+\])/;
undef(@diff);
}

testing whether diff is defined won't work in ruby anyway. Any time you
have an expression like this:

foo = 23 if expression

foo ends up being automagically defined anyway. After running that
code, if expression is false, foo == nil.

So, as Sean says, it would probably be better to use nil, unless
Delta_DHMS might return nil itself.

Oh! Which brings to mind something really neat I figured out awhile ago. If
Delta_DHMS really can return nil as a valid value, try re-writing the code
like this:

{
# date parsing code was here
@diff=Delta_DHMS(@binkdate,@today) if /(\[\d+\])/;
print $trimmed $_ if $diff[0] < $ARGV[1] && @diff != :undefined;
next if @diff != :undefined;
print $trimmed $_ if ! /(\[\d+\])/;
@diff = :undefined;
}

Initialize @diff = :undefined in your class initialize method. :undefined
will be a Ruby symbol that gets created on its first use. From there on out,
just set @diff to :undefined whenever you need to "undefine" it.

To me this seems simpler:

while ( diff = /(\[\d+\])/ && Delta_DHMS(@binkdate, @today) )
print ...
end

robert
 
T

tony summerfelt

I'm aware what they do, but you can get the desired behavior
using nil. I mean, you're trying to use Ruby, not Perl right?

the example i posted was for perl, but if the 'nil' will work for ruby
i'll try it...which sorta answers my original question :)
 
T

tony summerfelt

print $trimmed $_ if $diff[0] < $ARGV[1] && defined(@diff);
Here you check that @diff is defined after trying to access an element
of diff, is that right?

that perl code means a line read from the log file is written to an
archive file IF the date matches the criteria AND that @diff exists
print $trimmed $_ if diff && diff[0] < ARGV[1]

except that in this case @diff may contain a '1' or other garbage. to
avoid that, it's undefined and only defined when it's assigned valid
data.

before i settled on that particular line of code, i tried other
things...that was the shortest that worked...
 
T

tony summerfelt

it would be a local variable i'd be undefining, probably not an
instance variable (although i'd like that option also)

only if the logic you use makes the code smaller or more efficient...

larry wall added it to perl for a reason, and i'm guessing that he
thought it would be handy :)
how to use such an undefine action in a clean way
is something I have yet to figure out ;-)

i guess the code posted didn't do it for you? :)

i wrote a nodelist processor for fidonet's nodelist, where i also used
defined/undef. it's quick and dirty way to make sure you're working
with valid data...
BTW: defined?() tells you about whether a variable
is defined, including local ones.

unfortunatley it doesn't do me any good, as i'll want to undef it
later.
 
J

Josh Huber

tony summerfelt said:
unfortunatley it doesn't do me any good, as i'll want to undef
it later.

Yes, but I think you may have missed something which (I think)
was mentioned earlier -- ruby automatically "defines" local
variables when they are parsed. Try it in irb:

irb(main):001:0> p a
NameError: undefined local variable or method `a' for main:Object
from (irb):1
irb(main):002:0> a = 1 if false
=> nil
irb(main):003:0> p a
nil
=> nil
irb(main):004:0> p a.id
4
=> nil

So, using defined? in the way you used it in perl is really not
going to help you... Even though the "a = 1" was not evaluated,
a still becomes a local variable, bound to nil.
 
M

Mark Hubbart

it would be a local variable i'd be undefining, probably not an
instance variable (although i'd like that option also)

I think the whole point here is that it isn't Ruby-ish to rely on a
variable being defined or not. Ruby wassn't built to do things in that
way; a couple examples in this thread show how variables are
automagically defined when code is parsed. They aren't defined at
runtime, they are defined at eval time. So basically, If you are
translating code from Perl that undefines local variables, you will
have to find a different way of doing it, due to the way Ruby was
designed. I doubt that this is likely to change, because it's part of
how Ruby was designed.

If you know Ruby well, there is almost certainly a way to do it that is
just as reasonable and sensical as the Perl way, but it would be
sensical for Ruby.
only if the logic you use makes the code smaller or more efficient...

larry wall added it to perl for a reason, and i'm guessing that he
thought it would be handy :)

It is very handy for Perl, I know :) I used to use it. But there are
other ways of doing the same sort of thing. To translate the given code
into Ruby, I would (assuming that Delta_DHMS() won't return nil) write
'next unless diff.nil?', then later, 'diff = nil'. If there's a chance
that the method might return nil, you can always use the trick Sean
posted elsewhere on this thread.
 
T

tony summerfelt

I think the whole point here is that it isn't Ruby-ish

i'm slowly learning the ruby way to do things...
If you know Ruby well, there is almost certainly a way to do it that is
just as reasonable and sensical as the Perl way, but it would be
sensical for Ruby.

i get the feeling i'm well on my way once i finish my current
project...
into Ruby, I would (assuming that Delta_DHMS() won't return nil) write
'next unless diff.nil?', then later, 'diff = nil'. If there's a chance
that the method might return nil, you can always use the trick Sean
posted elsewhere on this thread.

of course, i don't want to force ruby code to look/act like perl.
but i DO want to keep 'the ruby way' if at all possible. later on
when i know ruby a lot better and i have to go back to this code it
won't be too embarrassing :)

sometimes thinking in perl hampers me when i'm working in another
language...
 
J

Jean-Hugues ROBERT

On Jun 15, 2004, at 10:19 AM, tony summerfelt wrote:
I think the whole point here is that it isn't Ruby-ish to rely on a variable being defined or not. Ruby wassn't built to do things in that way; a couple examples in this thread show how variables are automagically defined when code is parsed. They aren't defined at runtime, they are defined at eval time.

For the sake of it:

def test(); p defined? x; x = "hello"; p defined? x; end
test() # => nil, "local-variable"

According to the definition of "defined" implemented by
defined?(), it appears that in fact a local variable is
not defined until it gets assigned. That necessarily
happens at runtime. However, at parse time (or eval time),
the compiler determines that some entity is going to be
a local variable... once it gets defined at runtime.

This is a very minor thing and I would be surprised
to seen some example of code taking advantage of that
behavior of defined?()

Yours,

JeanHuguesRobert
 
S

Sean O'Dell

I think the whole point here is that it isn't Ruby-ish to rely on a
variable being defined or not. Ruby wassn't built to do things in that
way; a couple examples in this thread show how variables are
automagically defined when code is parsed. They aren't defined at
runtime, they are defined at eval time. So basically, If you are
translating code from Perl that undefines local variables, you will
have to find a different way of doing it, due to the way Ruby was
designed. I doubt that this is likely to change, because it's part of
how Ruby was designed.

Actually, Matz could probably very easily expose variables as objects
themselves to be manipulated like anything else in Ruby. I don't think
because he hasn't done it yet constitutes a "design decision" as much as
"something he didn't do." It's not impossible, in other words, it's just a
feature that doesn't exist yet.

Sean O'Dell
 
F

Florian Frank

it would be a local variable i'd be undefining, probably not an
instance variable (although i'd like that option also)

In your code you used global variables, and they work different
in Perl than you seem to think. If you use a global variable
the Perl interpreter reserves an entry in the stash of the
package of the global variable. If you do "undef $a" you do
the equivalent of "$a = undef". This example shows, that
the entry exists even without assigning a value to the variable
$a:

perl -MData::Dumper -e 'sub d { print Dumper [ map { $_, ${"$_"} }\
grep { /^a$/ } keys %{*{main::}} ] }; d(); $a; d(); '

If you use @a as a global variable it's no different, in fact
the same entry is used, but you can save different things to this entry
at the same time: scalars (those can be references or blessed
references, too), globs, code objects, arrays and hashes. (Thanks
for reminding me how horrible Perl's internals are, ugh!)

If you call defined on @a, what you actually do is checking if the
array @a contains any elements, because the stash entry exists in any
case. To use defined for aggregates is deprecated, see
perldoc -f defined:

: Use of "defined" on aggregates (hashes and arrays) is depre- cated.
: It used to report whether memory for that aggregate has ever been
: allocated. This behavior may disappear in future versions of Perl.
: You should instead use a simple test for size:
:
: if (@an_array) { print "has array elements\n" }
: if (%a_hash) { print "has hash members\n" }

Ruby's global variables work the same way as Perl's do. But if
you use lexical variables (starting with downcased letters),
the variables is !defined? until the interpreter sees an
assignment to it. It's BTW not necessary to execute the
assignment:

ruby -e 'p defined?(a); false and a = nil ; p defined?(a)'

If you use lexical variables in Perl you have to use "my $a", to reserve
memory for it in the current scope. In Perl it's of course not possible
to have a lexical variable that is undefined in the Ruby way, that is,
undefined before the "my $a", because it would be interpreted by Perl as
a global variable. This would lead to an entry for it in the stash like
shown above.
only if the logic you use makes the code smaller or more efficient...

Premature optimization is the root of all evil...

[defined?]
unfortunatley it doesn't do me any good, as i'll want to undef it
later.

So you can do "a = nil" or "$a = nil" and check for a.nil? to be
true. Or perhaps better just rely on the fact that nil is false in
Ruby. Using nil will be equivalent to "undef $a" in Perl.
 
M

Mark Hubbart

Actually, Matz could probably very easily expose variables as objects
themselves to be manipulated like anything else in Ruby. I don't think
because he hasn't done it yet constitutes a "design decision" as much
as
"something he didn't do." It's not impossible, in other words, it's
just a
feature that doesn't exist yet.

Yes, I agree, it is possible that Matz could implement that. I think
though that it would be less of an addition than a conversion. For
example:

foo = 23 unless true
p defined? foo

Will print "local-variable". The code foo in which foo was assigned to
was not run, so the '=' operator was never really applied to it. So if
there was a Variable class, and the '=' operator was its method, that
method would not be called in the above code. Because of this, I
strongly suspect the above would print "nil" if there was a Variable
class.

I may not be understanding it fully (I'm self-taught, there are many
gaps in my knowledge) but it *looks* like a design decision to me, and
'variables as objects' couldn't be implemented without a non-trivial
change to the way the language works. But I could easily be wrong :)

cheers,
Mark
 
S

Sean O'Dell

Yes, I agree, it is possible that Matz could implement that. I think
though that it would be less of an addition than a conversion. For
example:

foo = 23 unless true
p defined? foo

Will print "local-variable". The code foo in which foo was assigned to
was not run, so the '=' operator was never really applied to it. So if
there was a Variable class, and the '=' operator was its method, that
method would not be called in the above code. Because of this, I
strongly suspect the above would print "nil" if there was a Variable
class.

I may not be understanding it fully (I'm self-taught, there are many
gaps in my knowledge) but it *looks* like a design decision to me, and
'variables as objects' couldn't be implemented without a non-trivial
change to the way the language works. But I could easily be wrong :)

I looked at the BLOCK structure that is the C representation of the binding
object, but I only learned two things. One, I can't really tell without
spending a lot more time poking around how dyna_vars really binds a
symbolically named internal variable to an object and two, you probably could
create internal variable objects to represent them. I don't see why not.

Probably it would work best through the Binding object itself. Matz, or
someone who understands how the BLOCK structure is used well enough, could
add methods to Binding to add and remove variables, and if a Variable class
were written to point into the variable it represents in a BLOCK structure,
it could probably also return objects to represent the variable.

Sean O'Dell
 
T

tony summerfelt

In your code you used global variables, and they work different
in Perl than you seem to think.

actually i used local variables, the code was an excerpt...
So you can do "a = nil" or "$a = nil" and check for a.nil? to be
true. Or perhaps better just rely on the fact that nil is false in
Ruby. Using nil will be equivalent to "undef $a" in Perl.

that seems to be the way to go...when i know ruby better my question
will probably be moot :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,120
Latest member
ShelaWalli
Top