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

Missing regex globals $` and $' #1202

Closed
stugol opened this issue Aug 17, 2015 · 35 comments
Closed

Missing regex globals $` and $' #1202

stugol opened this issue Aug 17, 2015 · 35 comments

Comments

@stugol
Copy link

stugol commented Aug 17, 2015

I use the regex globals $` and $' in Ruby. What is the Crystal alternative to these?

@bjmllr
Copy link
Contributor

bjmllr commented Aug 17, 2015

I opened a PR to add MatchData#pre_match and MatchData#post_match: #1207

If that's merged, you could use something like $~.pre_match, though I wouldn't recommend using global variables unless you really need to, in either language.

As an aside, this question would be rather cryptic to anyone who doesn't already know about Ruby's regexp globals, since they're neither self-explanatory nor googleable. I only know $` and $' (aka $PRE_MATCH and $POST_MATCH) because I used to write a lot of Perl. It's good that this question is focused, but it's best to err on the side of providing too many details when asking a question.

@PragTob
Copy link
Contributor

PragTob commented Aug 17, 2015

Does crystal really want to support all those weird global variables? I'd prefer it'd rather not... possibly not any, I think it leads to bad style.

@stugol
Copy link
Author

stugol commented Aug 17, 2015

@bjmllr thank you. How would I go about merging your fix into my local copy of the source on my hard drive?

@PragTob The question is less "should we have global variables" and more "shouldn't there be some way to get this information". It doesn't really matter how you query the data (although personally I like Ruby's special global a), just that you can.

@stugol
Copy link
Author

stugol commented Aug 17, 2015

Globals, I meant. Not global a. Stupid phone.

@bjmllr
Copy link
Contributor

bjmllr commented Aug 17, 2015

I would prefer to see even $~ and $1, $2, etc go away. The rubocop style guide suggests avoiding those and using Regexp.last_match instead, but that's still global state so I never use any of them. IMHO they make some sense if you are writing one-liners, and there is crystal eval, but I don't think one-liners play to Crystal's strengths.

@stugol Using git, you can add my fork as a remote and then pull my feature branch into a local branch.

@0x1eef
Copy link

0x1eef commented Aug 17, 2015

in Ruby $~, $1, $2 etc aren't true global variables. they act as pseudo global variables which means they aren't even thread local but more like a local variable that can come and go.

@bjmllr
Copy link
Contributor

bjmllr commented Aug 17, 2015

@strcmp Thanks for the correction. I guess the only reason to eliminate them would be for style, then.

@0x1eef
Copy link

0x1eef commented Aug 17, 2015

yes many people consider them to be a perlism that should be replaced with something else like Regexp.last_match (it has same semantics as $~).

@jhass
Copy link
Member

jhass commented Aug 17, 2015

Crystal already has chosen to emit MatchData, instead of just String in some APIs, most notable String#scan. I yet have to see a usecase for any of the pseudo globals (they're thread local in Crystal too afaik), or even Regex.last_match that can't be replaced with something else that uses an explicitly returned MatchData or doesn't have a need to access it in the first place. That actually holds for Ruby too.

@asterite
Copy link
Member

The use case is "case", but I'm honestly not sure it's worth all the trouble. At least they are concurrency safe.

@PragTob
Copy link
Contributor

PragTob commented Aug 17, 2015

@asterite

why is case the use case?

Can't you do (didn't check code for correctness):

match = str.match /regex/
case match
#...

what am I missing?

@asterite
Copy link
Member

Try handling more than one regex and getting the captured groups in each case. Sorry, I can't code from a cellphone

@PragTob
Copy link
Contributor

PragTob commented Aug 17, 2015

Ah I see, thanks for explaining @asterite !

@vendethiel
Copy link
Contributor

They have even less value if you admit crystal is probably not going to be used for one-liners (where they do make sense) ;-).

@stugol
Copy link
Author

stugol commented Aug 17, 2015

I think these pseudo-globals have a definite use. case statements should be as flexible as possible, in my opinion. Why limit the flexibility of the language just to satisfy some arbitrary OCD "don't use globals" rule?

@stugol
Copy link
Author

stugol commented Aug 17, 2015

Why not just add $` and $' pseudo-globals? Crystal is based on Ruby, so why go out of our way to do things differently? We have $~ and $1, after all.

@vendethiel
Copy link
Contributor

Do $` and $' offer a performance problem (the first time they're used) like in Perl5 or not?

@stugol
Copy link
Author

stugol commented Aug 17, 2015

@bjmllr I can't compile your changes. An attempt to make the project results in this error:

CRYSTAL_CONFIG_PATH=`pwd`/src ./bin/crystal build  -o .build/crystal src/compiler/crystal.cr
Using compiled compiler at .build/crystal
/usr/bin/ld: cannot find -lpcre
collect2: error: ld returned 1 exit status
Error: execution of command failed with code: 1: `cc -o /home/infinity/crystal/.crystal/crystal-run-macro-run-_home_infinity_crystal_src_ecr_process.cr.tmp "/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o"   -levent -lrt -lpcl -lpcre -lgc -lpthread -lunwind`
Makefile:25: recipe for target '.build/crystal' failed
make: *** [.build/crystal] Error 3

I previously compiled the project without issue.

@stugol
Copy link
Author

stugol commented Aug 17, 2015

Also I'll be damned if I can get my head around the use of git.

> rm crystal -rf
> git clone https://github.com/manastech/crystal.git
> cd crystal
> git remote add prematch https://github.com/bjmllr/crystal.git
> git pull prematch 1a7a2cd6d81ca85aa2c14d30e5a1e647d241857f
error: no such remote ref 1a7a2cd6d81ca85aa2c14d30e5a1e647d241857f

Dammit, why does everything have to be so complicated?

Also, why did these commands work last time, and don't work now??

@bjmllr
Copy link
Contributor

bjmllr commented Aug 17, 2015

/usr/bin/ld: cannot find -lpcre

@stugol, the linker isn't able to find PCRE on your system. FWIW I didn't touch the C bindings.

@stugol
Copy link
Author

stugol commented Aug 17, 2015

Well someone did. And I can't install PCRE because I have no way of knowing which PCRE is required. On my Debian box, the options are:

libpcre++0         libpcre3-dbg       libpcrecpp0        libpcre-ocaml
libpcre3           libpcre3-dev       libpcre++-dev      libpcre-ocaml-dev

@refi64
Copy link
Contributor

refi64 commented Aug 17, 2015

Use libpcre3-dev.

@stugol
Copy link
Author

stugol commented Aug 18, 2015

Would it be too much trouble for the code to actually compile, please?

CRYSTAL_CONFIG_PATH=`pwd`/src ./bin/crystal build  -o .build/crystal src/compiler/crystal.cr
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `*Fiber::new<&( -> Void)>:Fiber':
main_module:(.text+0x10f2): undefined reference to `co_set_data'
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `*Fiber#resume<Fiber>:Void':
main_module:(.text+0x1230): undefined reference to `co_get_data'
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `*FileDescriptorIO#unbuffered_write<FileDescriptorIO, Slice(UInt8), Int32>:Int32':
main_module:(.text+0x1706): undefined reference to `co_get_data'
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `~fun_literal_9':
main_module:(.text+0x19b1): undefined reference to `co_get_data'
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `main':
main_module:(.text+0x2ca9): undefined reference to `GC_get_push_other_roots'
main_module:(.text+0x2cc7): undefined reference to `GC_set_push_other_roots'
main_module:(.text+0x2ccc): undefined reference to `co_thread_init'
main_module:(.text+0x2d7e): undefined reference to `co_set_data'
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `*File@BufferedIOMixin#close<File>:(Nil | Void)':
main_module:(.text+0x5919): undefined reference to `co_get_data'
/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o: In function `*File@FileDescriptorIO#unbuffered_read<File, Slice(UInt8), Int32>:Int64':
main_module:(.text+0x5c75): undefined reference to `co_get_data'
collect2: error: ld returned 1 exit status
Error: execution of command failed with code: 1: `cc -o /home/infinity/crystal/.crystal/crystal-run-macro-run-_home_infinity_crystal_src_ecr_process.cr.tmp "/home/infinity/crystal/.crystal/home/infinity/crystal/src/ecr/process.cr/main.o"   -levent -lrt -lpcl -lpcre -lgc -lpthread -lunwind`
Makefile:25: recipe for target '.build/crystal' failed
make: *** [.build/crystal] Error 3

@refi64
Copy link
Contributor

refi64 commented Aug 18, 2015

@stugol

main_module:(.text+0x2ca9): undefined reference to `GC_get_push_other_roots'
main_module:(.text+0x2cc7): undefined reference to `GC_set_push_other_roots'

Download the Boehm GC yourself, install it, and delete the libgc.* files in /usr/lib.

@refi64
Copy link
Contributor

refi64 commented Aug 18, 2015

For the others, the library used for coroutines (forgot the name!) is also too old. Build and install it manually.

I love Ubuntu, but the packages can get pretty old sometimes. :)

@stugol
Copy link
Author

stugol commented Aug 18, 2015

Wait... I have to download and build two other programs that I've never even heard of, before I can build the latest version of Crystal?

But I managed to build whatever the current version was three days ago with no problems. What's changed?

Where does this end? Suppose these other things require further dependencies? Debian has a package manager for a reason. If I go compiling stuff from source all over the place, I'm going to bork my installation. Again.

It worked three days ago. Why can't it just work now?

@kostya
Copy link
Contributor

kostya commented Aug 18, 2015

not need to build this libs, just set LIBRARY_PATH to downloaded crystal.
export LIBRARY_PATH=/home/kostya/crystal-0.7.6-1/embedded/lib/

@waj
Copy link
Member

waj commented Aug 18, 2015

@stugol right now when you install Crystal from .deb package for instance, it also comes with some precompiled binaries of the dependencies (in the future, custom packages for each distribution might be created). If you use the "crystal" wrapper installed by the package, it will add the libraries to the LIBRARY_PATH, so it should work.

I'm not sure what's going on in your setup. Please, try running "make clean" first. No dependencies has changed in many days.

Most dependencies from Debian should serve the purpose for building Crystal. Some distros doesn't include recent enough versions of LLVM, libpcl and Boehm GC.

@stugol
Copy link
Author

stugol commented Aug 18, 2015

Seems the problem is caused by replacing the distro version of Crystal with the freshly-compiled version. Attempting to compile Crystal with a freshly-compiled Crystal fails.

@stugol
Copy link
Author

stugol commented Aug 18, 2015

@bjmllr Also, I don't know how to pull your regex changes without pulling your entire fork. And your fork is massively outdated, according to the page.

I really don't know what I'm doing with git.

@PragTob
Copy link
Contributor

PragTob commented Aug 18, 2015

Can we please stay on topic here and move setup/configuration problems to a separate thread?

@jhass
Copy link
Member

jhass commented Aug 31, 2015

#1207 is merged, I vote against adding more (pseudo) globals than necessary. Can we close this?

@stugol
Copy link
Author

stugol commented Aug 31, 2015

I personally would prefer to use the Ruby-style pseudo-globals, if you're asking for votes...

@asterite
Copy link
Member

@jhass Yes, we can close this, we can do $~.pre_match and $~.post_match. $~ and $1 are the most common uses, so having to write $~.pre_match instead of "$`" isn't bad.

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

10 participants