What is the $- magic global?

I’ve been searching for the past hour or so, including manually stepping
through the ruby parser code, trying to work out what the $- magic
global is or does.

I’ve gotten as far as the following:

ruby 2.1.0dev (2013-04-24 trunk 40429) [x86_64-linux]

irb(main):001:0> $-
irb(main):002:0> $-.inspect
=> “nil”
irb(main):003:0> a = $-
irb(main):004:0> a
=> nil
irb(main):005:0> $- = 42
=> 42
irb(main):006:0> b = $-
irb(main):007:0> b
=> 42

So it appears to be suppressing output in irb, in some strange way. I
also note the following behaviour:

irb(main):001:0> $-
irb(main):002:0>
=> nil
irb(main):003:0> $- = 42
=> 42
irb(main):004:0> $-
irb(main):005:0>
=> 42
irb(main):006:0> $-
irb(main):007:0> :a
=> :a

It appears that the value of $- isn’t returned until I hit enter a
second time, but only if there’s no intervening value (whitespace is
ignored).

What’s going on?!

Also note: it’s impossible to search on Google for “$-” because Google
is a jerk

Also: I’m aware of bash’s $- options description, but that doesn’t seem
relevant in this case; bash’s $- is a simple string, and doesn’t have
any magic attached.

I know that perl and ruby both have a similarly-defined $+ magic
variable. Perl also has a $- (“The number of lines left on the page of
the currently selected output channel.”) but I doubt there’s a
correlation with ruby’s, because perl’s is a simple integer, and is
related to $~ and $= which are completely different between the two
languages.

I’ve also encountered perl’s @-/@+ match offsets, but can’t see how
they’d be relevant.

Completely flummoxed.

On Tue, Apr 23, 2013 at 9:21 PM, Matthew K. [email protected]
wrote:

I’ve also encountered perl’s @-/@+ match offsets, but can’t see how
they’d be relevant.

Hummm… I’m flummoxed as well. I just went through the newest
Programming Ruby book (beta 2) and cannot find anything referencing
$-. It lists these:

$-0 → String Synonym for $/
$-F → String Synonym for $;
$-a → Object True if the -a option is specified on the command line
$-d → Object Synonym for $DEBUG.
$-i → String If in-place edit mode is enabled (perhaps using the -i
command-line option), $-i holds the extension used when creating the
backup file.
$-I → Array Synonym for $:
$-l → Object Set to true if the -l option (which enables line-end
processing) is present on the command line.
$-p → Object Set to true if the -p option (which puts an implicit
while gets…end loop around your program) is present on the command
line.
$-v → Object Synonym for $VERBOSE.
$-w → Object Synonym for $VERBOSE.
$-W → Object Return the value set by the -W command-line option.

and this:

“a global variable name can be formed using $- followed by a single
letter or underscore” [p 318 in PDF]

but no bare $- variable…

If you try it on http://repl.it/, $- immediately returns nil. Perhaps on
irb the interpreter is waiting for more input? I can’t test it right
now,
but what happens if you write something like the following?

$-x = 42
$-
x

Julio
@_joliv http://twitter.com/_joliv

On Wed, Apr 24, 2013 at 1:00 AM, tamouse mailing lists <

tamouse mailing lists wrote in post #1106716:

On Tue, Apr 23, 2013 at 9:21 PM, Matthew K. [email protected]
wrote:

I’ve also encountered perl’s @-/@+ match offsets, but can’t see how
they’d be relevant.

Hummm… I’m flummoxed as well. I just went through the newest
Programming Ruby book (beta 2) and cannot find anything referencing
$-. It lists these:

[snip]

and this:

“a global variable name can be formed using $- followed by a single
letter or underscore” [p 318 in PDF]

but no bare $- variable…

You know what, I think I realise what it is. I was being mislead by the
implicit definition of globals.

I think I was originally just typing $X-style globals in IRB to see what
happened, and in the process I hit $-, thus defining :‘$-’ as a symbol
in the global_variables list. Then whenever I checked global_variables
I was seeing $- as a defined (or at least known) symbol. Starting a new
ruby instance, I can see that $- isn’t defined from the start.

irb(main):001:0> $VERBOSE=true
=> true
irb(main):002:0> global_variables.select{|g| g.to_s == ‘$-’ }
=> []
irb(main):003:0> $-
irb(main):004:0>
(irb):3: warning: global variable `$-’ not initialized
=> nil
irb(main):005:0> global_variables.select{|g| g.to_s == ‘$-’ }
=> [:$-]
irb(main):006:0>

Also, having looked a bit closer at parse.y I think I see what’s going
on: when the parser encounters a ‘$’ followed by a ‘-’ it reads the next
character from input (trunk:parse.y#L7839), if it’s a identifier
character it adds it to the token, otherwise it pushes it back, then it
fixes the token, defines the symbol, and returns tGVAR. When I was
typing $- into IRB, there was no “next character” so the
nextc() call was blocking, then when I hit enter again, IRB fed
something (a newline or a NUL-byte or EOF or something) to the parser so
the blocked parse of the previous line was allowed to complete.

If I’m right, this can only happen in IRB, because any other stream will
either present a newline/NUL or trigger an EOF, causing nextc() to
return.

Julio Olivera wrote in post #1106717:

If you try it on http://repl.it/, $- immediately returns nil. Perhaps on
irb the interpreter is waiting for more input? I can’t test it right
now,
but what happens if you write something like the following?

$-x = 42
$-
x

Julio
@_joliv http://twitter.com/_joliv

I think that’s the right track. There’s something a little bit magic
going on in IRB, because the second line is treated as a whole new line,
thus:

irb(main):001:0> $-x = 42
=> 42
irb(main):002:0> $-
irb(main):003:0> x
NameError: undefined local variable or method x' for main:Object from (irb):3 from /usr/local/bin/irb21:12:in
irb(main):004:0> $-
irb(main):005:0> 1
=> 1

Whatever it is, I guess the upshot is “don’t use $- at the end of a line
in IRB”.

On Wed, Apr 24, 2013 at 7:34 AM, Nobuyoshi N.
[email protected]wrote:

It’s just an ordinary global variable, and is disallowed now in the

trunk.

I believed ordinary variables had to be valid identifiers.

It’s just an ordinary global variable, and is disallowed now in the
trunk.
Thank you.

Xavier N. wrote in post #1106724:

I believed ordinary variables had to be valid identifiers.

Yes, it was a valid identifier, till now.

On Wed, Apr 24, 2013 at 7:51 AM, Nobuyoshi N.
[email protected]wrote:

Xavier N. wrote in post #1106724:

I believed ordinary variables had to be valid identifiers.

Yes, it was a valid identifier, till now.

I mean, I believed that ordinary variables (the ones a user can define,
different from special-cased globals), had to have a valid identifier
following the dollar sign. I don’t know, you can’t assign to $| for
example.

Or is that $- was special-cased by the parser as a side-effect, but
still
had no special meaning so it was at the disposal of the user?

On Tue, Apr 23, 2013 at 10:42 PM, Matthew K. [email protected]
wrote:

Julio
irb(main):003:0> x
NameError: undefined local variable or method x' for main:Object from (irb):3 from /usr/local/bin/irb21:12:in
irb(main):004:0> $-
irb(main):005:0> 1
=> 1

Whatever it is, I guess the upshot is “don’t use $- at the end of a line
in IRB”.

A little off-topic, what not to put at the end of lines in IRB also
applies to the symbol literals :- and :+ .
In a previous conversation…

https://groups.google.com/d/msg/ruby-talk-google-deleted-39f2c/GPfpRGASBwo/g9UAU0kLzkQJ

…the issue of IRB parsing, specifically with specific characters as
the last character of a line, came up and similar IRB behavior was
noticed then.

$ irb
1.9.3p194 :001 > x = :-
1.9.3p194 :002 >
1.9.3p194 :003 > “hi”
=> “hi”
1.9.3p194 :004 > x
=> :-

So yeah, the working theory then was that any valid token who’s last
character looks like an operator ($-, :-, :+, others?) will make IRB
think the line isn’t finished. I guess someone could just read IRB’s
code to verify…

It’s not documented in English.rb so it has not been aliased to a
REALLY_LONG_VARIABLE_4JAVA_DEVS

The posix shell definition for $- is:

$- (hyphen) Expands to the current option flags (the single-letter
option names concatenated into a string) as specified on invoca-
tion, by the set built-in command, or implicitly by the shell.

I see no reason for ruby to have it defined differently.

English.rb is well documented in 2.0:

$ERROR_INFO:: $!

$ERROR_POSITION:: $@

$FS:: $;

$FIELD_SEPARATOR:: $;

$OFS:: $,

$OUTPUT_FIELD_SEPARATOR:: $,

$RS:: $/

$INPUT_RECORD_SEPARATOR:: $/

$ORS:: $\

$OUTPUT_RECORD_SEPARATOR:: $\

$INPUT_LINE_NUMBER:: $.

$NR:: $.

$LAST_READ_LINE:: $_

$DEFAULT_OUTPUT:: $>

$DEFAULT_INPUT:: $<

$PID:: $$

$PROCESS_ID:: $$

$CHILD_STATUS:: $?

$LAST_MATCH_INFO:: $~

$IGNORECASE:: $=

$ARGV:: $*

$MATCH:: $&

$PREMATCH:: $`

$POSTMATCH:: $’

$LAST_PAREN_MATCH:: $+

$xxxx is create a global variable, or return nil (if it is not ruby
predefined).

xxxx is valid variable name.

2013/4/27 Stu [email protected]