Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map { "$_", 1} @array is syntax error #2872

Closed
p5pRT opened this issue Nov 17, 2000 · 7 comments
Closed

map { "$_", 1} @array is syntax error #2872

p5pRT opened this issue Nov 17, 2000 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 17, 2000

Migrated from rt.perl.org#4723 (status was 'resolved')

Searchable as RT4723$

@p5pRT
Copy link
Author

p5pRT commented Nov 17, 2000

From Bruce.Albrecht@fingerhut.com

Created by bruce.albrecht@fingerhut.com

I was trying to do
  %hash = map { "\L$_", 1 } @​array
but it appears that any construct of the form​:
  map { "string", 1 }
causes a syntax error. I have found a work around for this​:
  map { ("\L$_", 1) } @​array

This is also broken in 5.005.03.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl v5.6.0:

Configured by w246 at Wed Mar 29 12:36:29 CST 2000.

Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration:
  Platform:
    osname=solaris, osvers=2.6, archname=sun4-solaris
    uname='sunos gf003e0 5.6 generic_105181-17 sun4u sparc sunw,ultra-2 '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=undef d_sfio=undef uselargefiles=define 
    use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef
  Compiler:
    cc='cc', optimize='-O', gccversion=
    cppflags='-I/usr/local/gnu/include'
    ccflags ='-I/usr/local/gnu/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    stdchar='unsigned char', d_stdstdio=define, usevfork=false
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, usemymalloc=y, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-L/usr/local/lib -L/usr/local/gnu/lib -L/usr/ccs/lib '
    libpth=/usr/local/lib /usr/local/gnu/lib /lib /usr/lib /usr/ccs/lib
    libs=-lsocket -lnsl -lgdbm -ldl -lm -lc -lcrypt -lsec
    libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-KPIC', lddlflags='-G -L/usr/local/lib -L/usr/local/gnu/lib -L/usr/ccs/lib'

Locally applied patches:
    


@INC for perl v5.6.0:
    /usr/local/gnu/perl-5.6.0/lib/5.6.0/sun4-solaris
    /usr/local/gnu/perl-5.6.0/lib/5.6.0
    /usr/local/gnu/perl-5.6.0/lib/site_perl/5.6.0/sun4-solaris
    /usr/local/gnu/perl-5.6.0/lib/site_perl/5.6.0
    /usr/local/gnu/perl-5.6.0/lib/site_perl
    .


Environment for perl v5.6.0:
    HOME=/home/02/w246
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH=/usr/local/Harvest/lib:/usr/local/Harvest/FCP/Galaxy/lib:/opt/oracle/prodvers/lib:/usr/dt/lib:/usr/lib:/opt/oracle/prodvers/lib:/usr/local/dt/lib:/usr/openwin/lib:/opt/SUNWspro3.0.1/lib:/usr/local/TeleUSE3.1.1/lib:/usr/local/gnu/lib
    LOGDIR (unset)
    PATH=/usr/local/Harvest/bin:/usr/local/Harvest/FCP/Galaxy/bin:/opt/oracle/prodvers/bin:/bin:/usr/bin:.:/home/02/w246/bin:/usr/local/bin:/usr/openwin/bin/xview:/usr/openwin/bin:/usr/ccs/bin:/opt/SUNWspro3.0.1/bin:/opt/SUNWguide/bin:/usr/local/softool/macros:/usr/local/stage/utilities/wb/prod/bin:/usr/local/stage/utilities/wb/prod/scripts:/usr/local/stage/apps/ccs/scripts:/opt/SUNWmfwm/bin:/usr/local/TeleUSE3.1.1/bin:/opt/oracle/prodvers/bin:/usr/local/xrunner/bin:/usr/local/gnu/bin:/usr/local/perl5/bin:/usr/local/Harvest/bin:/usr/ucb
    PERL_BADLANG (unset)
    SHELL=/bin/ksh


@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2000

From @tamias

On Fri, Nov 17, 2000 at 11​:01​:07AM -0600, Bruce Albrecht wrote​:

I was trying to do
%hash = map { "\L$_", 1 } @​array
but it appears that any construct of the form​:
map { "string", 1 }
causes a syntax error. I have found a work around for this​:
map { ("\L$_", 1) } @​array

Thank you for your report. This is actually a known issue.

With the advent of anonymous hash references, Perl has to determine whether
map { ... is the start of map BLOCK LIST, or map EXPR, LIST with an
anonymous hash as the expression.

Because Perl doesn't look ahead to the closing brace, it has to guess. If
the opening brace is followed by a string and a comma, Perl guesses that it
is an anonymous hash. Perl then expects to find a comma after the closing
brace, and reports a syntax error if there isn't one.

One workaround is to use parens, as you found. Another is to put a plus
before the string.

Because the workarounds are so simple, this bug does not have a high
priority for being fixed.

Ronald

@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2000

From [Unknown Contact. See original ticket]

Lightning flashed, thunder crashed and Ronald J Kimball <rjk@​linguist.dartmouth
.edu> whispered​:
| On Fri, Nov 17, 2000 at 11​:01​:07AM -0600, Bruce Albrecht wrote​:
|
| > I was trying to do
| > %hash = map { "\L$_", 1 } @​array
| > but it appears that any construct of the form​:
| > map { "string", 1 }
| > causes a syntax error. I have found a work around for this​:
| > map { ("\L$_", 1) } @​array
|
|
| Thank you for your report. This is actually a known issue.

Another fix for this specific instance is to use lc($_) instead of "\L$_".

-spp

@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2000

From @nwc10

On Fri, Nov 17, 2000 at 01​:27​:52PM -0500, Stephen P. Potter wrote​:

Lightning flashed, thunder crashed and Ronald J Kimball <rjk@​linguist.dartmouth
.edu> whispered​:
| On Fri, Nov 17, 2000 at 11​:01​:07AM -0600, Bruce Albrecht wrote​:
|
| > I was trying to do
| > %hash = map { "\L$_", 1 } @​array
| > but it appears that any construct of the form​:
| > map { "string", 1 }
| > causes a syntax error. I have found a work around for this​:
| > map { ("\L$_", 1) } @​array
|
|
| Thank you for your report. This is actually a known issue.

Another fix for this specific instance is to use lc($_) instead of "\L$_".

but currently it's not documented as a trap. maybe I went a bit over the
top​:

*** pod/perlfunc.pod.orig Tue Nov 14 18​:56​:07 2000
--- pod/perlfunc.pod Fri Nov 17 20​:55​:37 2000
***************
*** 2483,2488 ****
--- 2483,2511 ----
  most cases. See also L</grep> for an array composed of those items of
  the original list for which the BLOCK or EXPR evaluates to true.
 
+ C<{> starts both hash references and blocks, so C<map { ...> could be either
+ the start of map BLOCK LIST or map EXPR, LIST. Because perl doesn't look
+ ahead for the closing C<}> it has to take a guess at which its dealing with
+ based what it finds just after the C<{>. Usually it gets it right, but if it
+ doesn't it won't realize something is wrong until it gets to the C<}> and
+ encounters the missing (or unexpected) comma. The syntax error will be
+ reported close to the C<}> but you'll need to change something near the C<{>
+ such as using a unary C<+> to give perl some help​:
+
+ %hash = map { "\L$_", 1 } @​array # perl guesses EXPR. wrong
+ %hash = map { +"\L$_", 1 } @​array # perl guesses BLOCK. right
+ %hash = map { ("\L$_", 1) } @​array # this also works
+ %hash = map { lc($_), 1 } @​array # as does this.
+ %hash = map +( lc($_), 1 ), @​array # this is EXPR and works!
+
+ %hash = map ( lc($_), 1 ), @​array # evaluates to (1, @​array)
+
+ or to force an anon hash constructor use C<+{>
+
+ @​hashes = map +{ lc($_), 1 }, @​array # EXPR, so needs , at end
+
+ and you get list of anonymous hashes each with only 1 entry.
+
  =item mkdir FILENAME,MASK
 
  =item mkdir FILENAME

map(lc($_),1),@​foo versus map+(lc($_),1),@​foo starts to look like something
for an obfuscated perl contest.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2000

From @jhi

On Fri, Nov 17, 2000 at 10​:10​:28PM +0000, Nicholas Clark wrote​:

On Fri, Nov 17, 2000 at 01​:27​:52PM -0500, Stephen P. Potter wrote​:

Lightning flashed, thunder crashed and Ronald J Kimball <rjk@​linguist.dartmouth
.edu> whispered​:
| On Fri, Nov 17, 2000 at 11​:01​:07AM -0600, Bruce Albrecht wrote​:
|
| > I was trying to do
| > %hash = map { "\L$_", 1 } @​array
| > but it appears that any construct of the form​:
| > map { "string", 1 }
| > causes a syntax error. I have found a work around for this​:
| > map { ("\L$_", 1) } @​array
|
|
| Thank you for your report. This is actually a known issue.

Another fix for this specific instance is to use lc($_) instead of "\L$_".

but currently it's not documented as a trap. maybe I went a bit over the
top​:

Applied, thanks.

@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2000

From @ysth

In article <20001117221028.A88930@​plum.flirble.org>,
Nicholas Clark <nick@​ccl4.org> wrote​:

+ C<{> starts both hash references and blocks, so C<map { ...> could be either
+ the start of map BLOCK LIST or map EXPR, LIST. Because perl doesn't look
+ ahead for the closing C<}> it has to take a guess at which its dealing with
+ based what it finds just after the C<{>. Usually it gets it right, but if it
+ doesn't it won't realize something is wrong until it gets to the C<}> and
+ encounters the missing (or unexpected) comma. The syntax error will be
+ reported close to the C<}> but you'll need to change something near the C<{>
+ such as using a unary C<+> to give perl some help​:
+
+ %hash = map { "\L$_", 1 } @​array # perl guesses EXPR. wrong
+ %hash = map { +"\L$_", 1 } @​array # perl guesses BLOCK. right
+ %hash = map { ("\L$_", 1) } @​array # this also works
+ %hash = map { lc($_), 1 } @​array # as does this.
+ %hash = map +( lc($_), 1 ), @​array # this is EXPR and works!

You left out my favorite!

Inline Patch
--- pod/perlfunc.pod.orig	Sat Nov 18 22:49:02 2000
+++ pod/perlfunc.pod	Sun Nov 19 12:11:24 2000
@@ -2495,7 +2495,8 @@
     %hash = map {  "\L$_", 1  } @array  # perl guesses EXPR.  wrong
     %hash = map { +"\L$_", 1  } @array  # perl guesses BLOCK. right
     %hash = map { ("\L$_", 1) } @array  # this also works
-    %hash = map {  lc($_), 1  } @array  # as does this.
+    %hash = map {  lc($_), 1  } @array  # as does this
+    %hash = map {; "\L$_", 1  } @array  # and this.
     %hash = map +( lc($_), 1 ), @array  # this is EXPR and works!
       
     %hash = map  ( lc($_), 1 ), @array  # evaluates to (1, @array)
End of Patch.

@p5pRT
Copy link
Author

p5pRT commented Nov 29, 2000

From @nwc10

On Sun, Nov 19, 2000 at 12​:13​:57PM -0800, Yitzchak Scott-Thoennes wrote​:

You left out my favorite!

--- pod/perlfunc.pod.orig Sat Nov 18 22​:49​:02 2000
+++ pod/perlfunc.pod Sun Nov 19 12​:11​:24 2000
@​@​ -2495,7 +2495,8 @​@​
%hash = map { "\L$_", 1 } @​array # perl guesses EXPR. wrong
%hash = map { +"\L$_", 1 } @​array # perl guesses BLOCK. right
%hash = map { ("\L$_", 1) } @​array # this also works
- %hash = map { lc($_), 1 } @​array # as does this.
+ %hash = map { lc($_), 1 } @​array # as does this
+ %hash = map {; "\L$_", 1 } @​array # and this.

that's quite nifty :-)

 %hash = map \+\( lc\($\_\)\, 1 \)\, @&#8203;array  \# this is EXPR and works\!

I also verified (after inspecting the code in toke.c) that having a literal
newline inside the "" string also makes it look not like-an-anon-hash
(the sniffer code looks to pair the qq() and find a "," or => all as
lookahead in the current line. Embedded literal \n means the close of the
q() isn't in the current buffer, so the {} is treated as block.
Interesting only in that it's actually a case of whitespace having
syntactic significance (sort of. arguably characters in strings are not
"whitespace" in the traditional sense).

Nicholas Clark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant