22 ms·
Java Verbal Expressions
- pandemic_region 6y agoWHERE HAVE YOU BEEN ALL MY LIFE
- laszlokorte 6y agois(4).equalTo(5.plus(eulers_constant.toThePowerOf(1.toTmaginaryUnit().times(rationBetweenCircumferenceOfACircleToItsDiameter))))
- aparsons 6y agoThe example isn’t a correct URL test regex (far from correct actually - even though there are plenty of edge cases regular regex strings tend to miss also)
- cfv 6y agoIt'd be absolutely bonkers if you could use this exact same DSL to generate valid strings
- recursive 6y agoWell, since you can use the regex itself to generate valid strings, it's certainly possible.
- m12k 6y agoYou can - use this to generate a regex, then run that regex through one of these libraries: https://stackoverflow.com/a/22133/126183 https://stackoverflow.com/a/22133/126183
- slifin 6y agohttps://github.com/lambdaisland/regal https://github.com/lambdaisland/regal Is a regex DSL that will let you do that, wouldn't be surprised to see others
- oweiler 6y agoI'm an average developer but never found regular expressions too hard to write or even read.
- theparanoid 6y agoAnything but the simplest regexes are tricky to correctly write.
- redmorphium 6y agoReminds me of https://github.com/francisrstokes/super-expressive https://github.com/francisrstokes/super-expressive
- PaulHoule 6y agoThat kind of thing works even better in Java because the static type system enforces it. In particular generic methods don't have the problem of type erasure that affect generic classes so many things you would want to do with types "just work". Almost everybody is afraid of it, but $ works just fine as an identifier and can be used to make a DSL that looks like jQuery in Java. Maybe someday i will write a class like: class("some.namespace.MyClass").method(...)
- miked85 6y agoI feel like one would be much better off and more efficient by just learning regular expressions.
- nerdponx 6y agoI agree. But if you want better readability and comments, Python's "verbose" regex (?x) is a beautiful thing. You can usually also just construct regular expressions incrementally by concatenating strings or whatever your language supports.
- hcarvalhoalves 6y agoThe fact there are countless RegEx cheatsheets and pages like https://regex101.com/ https://regex101.com/ or https://regexr.com/ https://regexr.com/ is evidence RegExes are not intuitive or easy to remember. Composing plain-english functions can be easier to remember, and editors can provide auto-complete.
- ed25519FUUU 6y agoThe argument isn’t that they’re easy to use, it’s that they’re widely used and widely available in virtually all languages. You’ll encounter them. The time it takes to learn regular expressions will pay off because you’ll be reading them and writing them for your whole career.
- king_magic 6y agoEh, not necessarily. 15 years into my career, I can count the number of times I've needed regular expressions on two fingers.
- setr 6y agoExcept that all implementations are subtly and annoyingly different, and while you can transfer your general understanding, you can’t avoid the cheatsheet if you’re using multiple tools. But of course, since this is basically a one-to-one mapping, you can also trivially transfer your understanding to any other regex tool anyways (with a cheatsheet, which you’ll need in either case).
- s4n1ty 6y agoWow, pretty sure I played with something like this for Python in the 90s. People have been trying to replace regexps with something more readable for a long time. This seems like a decent attempt, although the syntax for captures looks a little clumsy.
- jjice 6y agoWhile neat, I think that if you're a developer, you'd be better off learning basic regular expressions instead so you can use them in whatever language you'd like. Depending on this would probably just make moving to a new code base that doesn't use this a lot more confusing. A normal regex with a comment above it explaining what it does (for complex cases) always worked well for me.
- TonyTrapp 6y agoEven as a developer you may have to assemble a regular expression at runtime, at which point a library that can do it for you may be much more handy than having to assemble the string yourself. And even if you know regex by heart - assembling it with function calls can still be better / safer just like you shouldn't insert SQL parameters by hand into your SQL query strings.
- nsxwolf 6y agoI can't learn them. I've tried for over 20 years and every time I use them the knowledge is deleted from my brain immediately. A library like this would be very helpful if it worked. One problem is that I'm more likely to need regex almost anywhere but Java code.
- rhacker 6y agoAt the bottom there's a list of other languages that support the same API
- spatx 6y agoI think there is value in both cases. I've seen many developers that have struggled with regex even with all those hundreds of tools to learn and to build/test regex. This could be useful to them to start with, and they can learn regex according to their time/needs. I see solutions like this as a choice, and the fact that people are using these shows that there is value in having that choice, even if is not obvious to us at first glance.
- patal 6y agoThat does not work so well if you're working in a team. A fairly complex regular expression is always hard to read. We see this as early as in code review and as late as when you find a production bug because expectations of the surrounding code have changed. For those reasons, we usually break regexes into parts anyway, and name and comment the single parts. Using the library's example, we might have: protocol = "^(?:http)(?:s)?" protocol_separator = "(?:\:\/\/)" url = "(?:www\.)?(?:[^\ ]*)$" regex = protocol + protocol_separator + url Which turns out to be in the direction of these Java Verbal Expressions. I find the Verbal Expressions idea really enlightening.
- abhinai 6y agoBeautiful though a little verbose!
- cratermoon 6y agothis link has been posted 15 times on NH. First time was over 7 years ago https://news.ycombinator.com/item?id=6200070 https://news.ycombinator.com/item?id=6200070
- tomp 6y agoIs it just me or does this seem like a very bad idea? I mean it seems nicer but the reality is, if you don't know how Regexes work, you won't understand the nuances of the "verbal" regex either... Also, some optimisation maybe? ^(?:http)(?:s)?(?:\:\/\/)(?:www\.)?(?:[^\ ]*)$ could be better written as ^https?://(?:www[.])?[^ ]*$ Or am I missing something? In that case, I'll readily admit this library is a good idea :)
- lmilcin 6y agoNo, you are not. These "verbal" expressions are nothing more than a builder for actual expression. So you can't actually use it without understanding regular expressions.
- disgruntledphd2 6y agoThey're much easier to scan in a large codebase though, which I suspect is the major advantage.
- jariel 6y ago" These "verbal" expressions are nothing more than a builder for actual expression." It may be under the hood, but there's no reason for it to be. There's nothing inherent in our regexes that would imply they are 'the language' for that purpose, it just so happens we really only have one commonly used one. Like most things invented forever ago, there might be opportunities for a 'cleaner, better way'.
- lmilcin 6y agoObviously, there might be occasions to improve. But, regular expressions seem quite well optimize from my point of view. Regular expressions are used for exact same task regardless of programming language -- using single expression language regardless of programming environment seems like a huge advantage. It can be embedded in configuration file, as a string in a database, on a web page or deep in backend code, and it will still work the same. The "Java Verbal Expressions" already have "Java" in the name and so are complete loss when it comes to portability. Then comes the fact that "Java Verbal Expressions" are many times more code that actual regular expressions. That isn't easier to scan, it is much worse. Regular expressions are very succinct and you can express a lot in a single line of it. Comparable JVE-s would require many lines and wouldn't be more readable for anybody other than a person that doesn't know regexes at all.
- lmilcin 6y agoIt is a huge amount of code for a relatively simple expression. I see not a single situation where this would actually look more readably than a proper regex. Unless... you don't want to learn regular expressions and then you have two problems...
- deleted 6y ago[deleted]
- maweki 6y agoIt's pretty verbose, but it is useful in the sense that you have type-safety between character groups and the control characters. It's neat that it only allows you to create valid Regexes (I hope it does). At least you have static safety that your parenthesis for capture group are properly closed. This advantage is not explained. Not being able to construct invalid regular expressions is a good static safety guarantee that you don't get when you embed DSLs as strings. Edit: This is the same reason why we would prefer jOOQ to embedded String-SQL, if speed/dependencies are of no concern. You're not allowed to construct invalid SQL as the java-type-system gives you these guarantees when using an embedded DSL instead of a String-DSL. This is very powerful, but of course only works if the type system of the host language is powerful enough.
- gambler 6y agoOnce you start thinking about it, it's mind boggling that we have thousands of languages and yet most of them don't have built-in facilities to construct and parse grammars (at least context-free ones). Every single designer seems to think that their language is finally good enough and will not be used as a starting point for another one.
- throwaway_pdp09 6y agoBecause building in a parser is inappropriate; it isn't generally worth it. You use a separate tool or framework, you don't build it into a language.
- rbonvall 6y agoRaku (Perl 6) has grammars as first-class citizens: https://docs.raku.org/language/grammars#Creating_grammars https://docs.raku.org/language/grammars#Creating_grammars
- raiph 6y agoPerhaps Raku would be of interest to you. It was specifically designed to make it a good starting point for its ongoing replacement, Ship of Theseus style.[1] ---- The first half of this comment paints the big picture of Raku's approach to enabling this. The second shows actual code demonstrating the approach. ---- Raku has a built in grammar + actions formalism, and corresponding built in parsing/compiling machinery. Raku's grammars/actions are used to declare, parse, and compile Raku -- it is entirely defined in terms of itself. ---- Raku isn't just one language, but a collection of sub-languages, aka slangs. Each of these is comprised of a grammar/action pair. These are mixed together to form a composed result: "Raku". ---- Any slang can include grammar rules that invoke rules in other slangs with which its mixed. The slangs in standard Raku take advantage of this. Thus a function written in the Main (GPL) slang will accept regexes in some spots in the Main slang, with those regexes being parsed/compiled according to the Regex slang. This ability for slangs to use each other can be (and is, for the standard slangs) mutually recursive. Thus, just as an ordinary function written in the Main slang can include a regex in its code, so too a regex can include an ordinary function. This overall approach of weaving slangs together is called a "language braid"[2]. Multiple slangs are seamlessly woven together as if they were just one language -- because in fact they are, despite its declaration being broken out into slang modules. ---- User defined slangs can replace or modify the "official" standard slangs that ship together to comprise "Raku". Thus, at the most trivial level comes slang modules like Slang::Tuxic.[3] This was one of the first slangs. It is just a few lines of code written by a core Raku dev; it overrides a few existing minor rules to tweak the parsing of the Main slang to make another dev called Tux stop complaining about some syntax decisions he didn't like. More advanced slangs are internal DSLs such as Slang::SQL.[4] This weaves SQL and standard Raku code so that each can enrich the other. ---- Use of slangs is lexically scoped. That is to say, a slang can be invoked within a particular module, or function, or even just an `if` statement's True block, and at the end of that scope the slang's alteration of Raku vanishes. And if that was done in an inner scope rather than at the top level, then at the end of that scope, pop, the old Raku would return. (Thus lending a new twist to the Ship of Theseus[1] thought experiment.) ---- This last section includes code showing the approach in action, after a bit of introduction of what I will and won't include. Raku's grammars declare arbitrary parsers. One can arbitrarily override any part of an existing grammar by composing it into a new grammar with selective replacement of particular parts. But "them's big guns". Instead we'll stick with a simpler mechanism. It's still powerful, but it's particularly easy to use and demonstrate. A key element underlying what I show below is an alternate rule construct that's available in any Raku grammar. This makes it trivial and practical to add any number of new alternatives for particular grammatical "slots". The grammars used to declare Raku itself make use of this construct to declare much of its grammar. In particular, the Main slang does and then builds on that in a principled manner to exposes itself to user extension of those parts of its grammar. This is what we're going to see in action. There are over a dozen of these grammatical "slots". For our example here we'll extend the `postfix` slot: sub postfix:<!> ( \N ) { # Declare factorial op N > 2 ?? ( N * ( N - 1 )! ) !! N } say 5! # 120 The syntax aspect of this extension happens as soon as the opening brace of the operator's definition block is reached. This is why the use of `!` that's inside the block is correctly recognized, despite appearing before the block defining its semantics is even closed. While the syntax is utterly trivial (literally just the token `!` where the Main slang accepts postfix ops), the semantics are defined by the arbitrary body of the declaration. This body compiles into corresponding AST that is added to the MAIN slang's semantic actions class. To be crystal clear, this all happens at compile time, and this new op would be part of a module's compiled result if it were in that module, despite the code that declares the op being ordinary Raku code. ---- [1] https://en.wikipedia.org/wiki/Ship_of_Theseus https://en.wikipedia.org/wiki/Ship_of_Theseus [2] https://www.reddit.com/r/ProgrammingLanguages/comments/h89sc6/what_are_examples_of_language_syntaxes_which_do_a/fuq4pga/ https://www.reddit.com/r/ProgrammingLanguages/comments/h89sc... [3] https://github.com/FROGGS/p6-Slang-Tuxic https://github.com/FROGGS/p6-Slang-Tuxic [4] https://github.com/tony-o/perl6-slang-sql https://github.com/tony-o/perl6-slang-sql
- 1f60c 6y agoThe HN title isn't very informative. Maybe you could change it to something like: Java Verbal Expressions: a DSL for regular expressions
- ajainy 6y agoof course as others pointed out, writing direct exp might be optimal or every dev should learn about it. BUT in my whole career span, whenever I have to use regex, I spend couple of hrs learning and testing. This kind of library for Java open doors for many other things. (testibility, default library using default methods etc.., integration with streaming ). And as community adds to it, it can be optimized internally. All end user needs to do upgrade versions. Can be extended part of javax validation specs.
- murkle 6y agoAnother key point: makes the code readable!
- kleiba 6y agoLooking at the example, my immediate reaction was that the main advantage would be the `anything_but` method, relieving me from the cumbersome construction of stuff like this: (?:[^t]|t(?:[^r]|r(?:[^u]|u(?:[^m]|m[^p])))) What a time-saver it would be to write anything_but("trump") Except, then you look at the source code and see this: public Builder anythingBut(final String pValue) { return this.add("(?:[^" + sanitize(pValue) + "]*)"); } Sad face :(
- recursive 6y agoWhy would you be constructing stuff like that? It consumes the input string up until it differs. When is that useful in a regex?
- enricozb 6y agoHow else would you write that you want to match all strings that don't contain string X? If you were matching at a specific position, you should use a negative lookahead (?!xyz), but I think in some cases you might need the mess above.
- recursive 6y agoI can't imagine a case where the mess would be useful at all. Negative lookahead is the only way I can imagine this being possibly useful. I.E. "Give me a string that's not trump and has a vowel in it". Given "trunk", that mess above would match all of "trun". Would good is matching a prefix going to do ever?
- kleiba 6y agoIf you concede that the standard regex construct [^x] is a useful construct at all -- match any character except x -- why would should such a negative match be restricted to only a single character? Why not also allow for, say, match anything except the following _two_ characters in a row?
- yoz 6y agoSure, it's much easier to read, especially when it comes to finding and understanding a two-character diff in a 50-char regex. Sure, I get the benefits of type safety. Sure, it'll save me time debugging when I accidentally create an invalid regex. But what am I meant to do with all that time saved? Read a book? Write more code? I don't get it. Let me waste the time on a ludicrously arcane syntax where I spend half the time looking at every bracket trying to understand if it's a control character in that particular context, because the ego trip I get from mastering this ridiculousness is HUGE! (Yes, I understand regex syntax. I've been able to explain the phrase "zero-width negative lookbehind assertion" for the past twenty years. I inhaled the Friedl book and got utterly high on the idea that the awesome power of regular expressions - which are genuinely great in how they ease flexibility in accepting input - is entwined with their completely inhuman syntax. But I was wrong.)
- sixo 6y agoIt's fun to write regex but it is absolutely miserable to read it. This looks like an improvement.
- szatkus 6y agoIt is. For most parts regexes like "\d+" are ok, but when there is something more complicated I pull Verbal Expessions into a project. To these days reactions on CR were mostly positive or netural at worst. If it was built into the standard library I would probably use it instead of regex, but adding a new dependency and interfacing it with libraries that expect Java regex objects has its cost.
- maweki 6y ago> Sure, I get the benefits of type safety. It seems not ;) It's as if your java-compiler would stop warning you on forgotten semicolons and would instead error out during runtime when it reaches the statement with the missing semicolon. It's not your time saved. It's time saved not running the test suite, for example. An uncompilable regex is a category of errors that you can ban completely from your program. Like java bans syntax errors as a category of (runtime) errors. It's time saved as any developer will not break this in a way that is not a semantic error. It's time and mind saved not thinking about a whole class of errors.
- soco 6y agoLooks a bit abandoned though, doesn't it. Otherwise I'd love it for the safety and readability (while I'd still need to re-learn all what got forgotten in the last half a year before I used regex last time)
- justin_oaks 6y agoThis project would be better if it wasn't exactly a 1-to-1 mapping from words/methods to regular expressions. For example, the regex "\d+" maps to the code "digits().oneOrMore()". That doesn't read well in English because it's odd to have an adjective after the noun (i.e. we say "red bird" not "bird red"). Also, a serious weakness in regex is they are "write only", or hard to read. That's because they are compact and don't have discernible sections that are then assembled together. You can do that yourself in Java by assigning chunks of regex to variables and then concatenating them together, but the regex engine doesn't let you do that itself. You can't name sections of the regex or insert comments into it. The example ^(?:http)(?:s)?(?:\:\/\/)(?:www\.)?(?:[^\ ]*)$ could be better if it could be broken down into named pieces or commented like this: ^ (?:http)(?:s)? # http or https (?:\:\/\/) # :// (?:www\.)? # optional www. (?:[^\ ]*) # rest of URL (no spaces) $
- dmarlow 6y agoI love your example of how it should be explained. This helps people correlate the verbal aspects to the regex parts they described. This ultimately reinforces and helps people learn regex more deeply.
- throwaway_pdp09 6y agoI thought java regexes had comments? https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html#COMMENTS https://docs.oracle.com/en/java/javase/11/docs/api/java.base...
- justin_oaks 6y agoHuh, I didn't know that. I've read through a fair amount of Java code with regexes and never seen anyone use comments. Maybe it's because Java doesn't have proper multi-line string support built into the language. If you don't have multi-line support in the language then you're more likely to put the comments outside the string: String regex= "^" +"(?:http)(?:s)?" // http or https +"(?:\:\/\/)" // :// +"(?:www\.)?" // optional www. +"(?:[^\ ]*)" // rest of URL (no spaces) +"$";
- surfsvammel 6y agoUnlike many others, I actually like this idea. I know regular expression, but many of my colleagues do not. They often have a hard time understanding what a particular regex do, event though I often document them step by step. Something like this would make it more readable. I do agree with others here, that it seems a bit rough around the edges and some optimisation might be needed. But I think the idea itself is sound.
- maweki 6y agoMaybe you should look at visualizations like Regex Railroad Diagrams. This is what helps me most.
- jjevanoorschot 6y agoFor everyone that doesn't see the point, take a look at the example of parsing a long string [0]. The verbal expression is _much_ easier to read than the regular expression. [0] https://github.com/VerbalExpressions/JavaVerbalExpressions/wiki/Parse-long-strings-example https://github.com/VerbalExpressions/JavaVerbalExpressions/w...
- pavon 6y agoI don't see it. The regex is mostly hard to read because they formatted it poorly and put in a bunch of unnecessary non-capturing groups. I find this to be just as easy (if not easier) to read as their first example: String pattern = ( "(\d+)\t"+ "(\d+)\t"+ "([0-1])\t"+ "(http://localhost:20\d{3})\t"+ "([0-1])\t"+ "(\d+)\t"+ "([0-1])\t"+ "(\d+)\t"+ "(\d+)\t"+ "([0-1])\t"+ "(\d+)\t"+ "(STR[0-2])" ); And this is just as easy to read as their second example: String num = "(\d+)\t"; String bool = "([0-1])\t"; String url = "(http://localhost:20\d{3})\t"; String str = "(STR[0-2])"; String pattern = num+num+bool+url+bool+num+bool+num+num+bool+num+str; And yes, I do frequently split up my regexes like that to make them more readable. The only improvement I see is that you don't have messy escaping in the url. That is genuinely nice. It motivates me to start using an regEsc() function instead of doing it by hand. However, I find "capt().endCapture()", and other verboseness to be a step backwards. Edit: Actually, from what I can tell, all the escaping was unnecessary in this case as well. Updated examples without unneeded escape characters.
- bwestergard 6y agoThis is a nice API. It seems to get right up to the edge of becoming a parser combinator library. Is it actually improving performance to use the regular expressions internally to evaluate matches?
- ridaj 6y agoIs the implied contention that `regex().capt().digit().oneOrMore().endCapt().tab()` is easier to read than `([0-9]+)`? If so, maybe this isn't for everyone :)
- throwsofaraway 6y agoTrying to simplify something that doesn't simplify inherently isn't always a good idea. Regex is pretty close to the least level of abstraction that is necessary to get the job done. It could probably be improved on, but probably not by much. Some commenters below mentioned this Java syntax is a good idea and using endless number of regex cheatsheets as a testament to why regex is not simple enough and should be replaced. It's almost silly that this is even an argument on HN. Take for example quantum physics, there are lots of videos and guides that try to explain how it works, in fact some of the smartest people tried to explain it, even Richard Feynman. But he famously said if you think you understand quantum mechanics you don't understand quantum mechanics. Some things cannot be reduced any further, this does not mean those things are always simple in nature or somehow were designed in a convoluted way on purpose. At least when it comes to regex it's important to keep in mind what Einstein said, "everything should be as simple as possible but no simpler." It's ironic that people apply reductionism to simplify regex, a thing that itself one could argue is a prime example of reductionistic design, yet they complain it's too abstract while applying reductionism.
- stickfigure 6y agoThis is cool, but I'm disappointed to see the horrid builder pattern show up again. Imagine you had to use StringBuilder every time you wanted to manipulate a String? Just make all fields final and combine the builder and 'working' class into a single immutable object. Like String. `build()` everywhere is syntactic noise, and you either lose immutable safety (by passing around builders everywhere, as in the examples) or composability (by passing around the 'sealed' objects). Builders are an antipattern that should only be used in cases where extreme performance is required.
- x87678r 6y agoI wish you were interviewing me. This is Java world you're talking about and if you can't squeeze a dozen Gamma Design Patterns into your code you aren't good enough.
- noema 6y agoThe main intent of Builder isn't performance, but to avoid a combinatorial explosion of constructors for every possible set of parameters.
- lalaithion 6y agoSo why have constructors for every possible set of parameters? Why VerbalExpression.regex() .startOfLine().then("http").maybe("s") .then("://") .maybe("www.").anythingBut(" ") .endOfLine() .build(); Instead of new VerbalExpression() .startOfLine().then("http").maybe("s") .then("://") .maybe("www.").anythingBut(" ") .endOfLine();
- szatkus 6y agoBoth are equally readable to me, but with the builder pattern you have an ability to fork a builder. Cloning objects in Java could be messy.
- stickfigure 6y ago
- tasogare 6y agoI did a little class like this with a fluent API in C# to generate regex in a project that requires big ones. It make working with regex super easy and super maintainable.
- deleted 6y ago[deleted]
- chrisbrandow 6y agosolve a problem with regex: now you have 2 problems. well, now you have 3.
- prabhatjha 6y agoThis is a fantastic idea -- the kind you see and go why the heck this was not done before. Such a huge time saver.
- quickthrower2 6y agoTake 3 more steps in this direction and you can shed the regex entirely and have parser combinators
- TazeTSchnitzel 6y agoBy using this “builder” syntax you gain: • not having to distinguish special characters in the pattern being matched from special characters part of regex syntax • no ambiguity as to whether something is a digraph or not • no escaping hell • unambiguous human-readable names for all the regex features used • the ability to use whitespace to clearly separate different parts of the regex • the ability to comment parts of the regex It sounds great to me. Have you ever tried making a regex matching something with backslashes in it, and then you have to put that regex inside a string literal? Have you ever had to switch between different regex environments and not known which symbols require escaping, or what is the correct way to write something in a particular environment? I've had all these problems.
- TimTheTinker 6y agoMany of those gains can be had by using first-class and more full-featured regexes, like those that that are available in other languages (Ruby, Perl): - escaping hell isn't that much of a problem, since you're only ever escaping something once (not like a regex in a string) - several languages support separating regexes across several lines - regex commenting (including named groups) is a standard feature in many languages, and that's besides using first-class comments across multiple lines I think you do have a point about digraphs (or homographs), but unless I misunderstand, those would be a problem whether or not the character(s) are part of a string vs. a first-class regex. As for unambiguous human-readable names for regex features used, tools like this (https://regexr.com/ https://regexr.com/) are available and very effective. I might prefer Java Verbal Expressions over java.util.regex, but to me that's more of a knock on Java and its lack of proper, first-class regexes than anything else.
- TimTheTinker 6y agoI am all for developer ergonomics, and I'm a fan of Ruby... but the problems this library would add to a codebase/project seem too big to be worth the benefits: - non-standard syntax requiring its own documentation, which developers would have to consult separately (even if they already know regular expressions) to modify generated regular expressions - removing the ability to test and validate regular expressions independently of the codebase (say, in the terminal, a small shell script, or using an online tool) - a new rabbit hole to traverse when debugging a problem - assuming the security risks associated with handing over regex-building to a library built by someone else (even more so if the regex is parsing private or protected data) - adding a new dependency that may or may not be maintained in the future For those who would want to use this library, I would suggest using a separate tool to build and/or understand regular expressions. Here's one example, and I'm sure there are others: https://regexr.com/ https://regexr.com/
- ebiester 6y agoI wrote one of these in 2002, back in college, after being inspired by Icon and SNOBOL. From Wikipedia: s := "this is a string" s ? { # Establish string scanning environment while not pos(0) do { # Test for end of string tab(many(' ')) # Skip past any blanks word := tab(upto(' ') | 0) # the next word is up to the next blank -or- the end of the line write(word) # write the word } } I really think we lost out when we went toward regular expressions rather than SNOBOL/Icon syntax, but I don't think a direct substitute is as much the issue.
- dailygrind___ 6y agoI think Regex is too low-level and a problem worth abstracting. It works fine with simple patterns but I don't really see how a pattern like this: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_])?\??(?:[-\+=&;%@.\w_])#?(?:[\w]*))?)/ (https://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url?answertab=votes#tab-top https://stackoverflow.com/questions/161738/what-is-the-best-...) contributes to readability.
- mrkeen 6y agoEven though I still use regexes in rare circumstances - e.g. inside config files, parser combinators already do a much better job than this (or regexes) when you are writing maintainable code: warcEntry = do header <- warcHeader crlf body <- do contentLength <- getContentLength header compressionMode <- getCompressionMode header warcbody contentLength compressionMode crlf crlf return (WarcEntry header body) If you accept crlf as "carriage-return-line-feed", the rest basically reads as pseudocode. crlf could have just as easily been written (string "\r\n") I guess. Parser combinators can: * call out to other parsing functions (e.g. warcHeader) - so you can build your code out of testable units. * bind results to variables and start using them during the parse, e.g. warcHeader returns data containing contentLength and compressionMode, which is then fed to the warcbody function so it knows what to expect.
- one-punch 6y agoParser combinators showed me what an expressive language (in particular Haskell) can do to let you write code as you intend, so that maintainable code is enjoyable to read, write, and reason about. I have heard that some people first “get” Haskell because of parser combinators.
- Tainnor 6y ago> call out to other parsing functions yes, regular expressions cannot do that because regular languages cannot do that. that is an important limitation of regular languages, otherwise you'd be able to match the language {a^nb^n for any n} (or more specifically, balanced parentheses). The thing you wrote you wouldn't want to parse with a regular expression because it fundamentally doesn't look like a regular language with its hierarchical structure.
- zvrba 6y agoI limit my brain-time on constructing a regex to 5 minutes max. If it takes me longer than that, I reach for a parser. Pick the right tool for the job.
- chubot 6y agoRelated: Oil has an regex syntax that composes and doesn't have escaping problems: https://www.oilshell.org/release/latest/doc/eggex.html https://www.oilshell.org/release/latest/doc/eggex.html Direct link to example: https://www.oilshell.org/release/latest/doc/eggex.html#example-of-pattern-reuse https://www.oilshell.org/release/latest/doc/eggex.html#examp... A longer example: http://www.oilshell.org/blog/2019/12/22.html#eggex http://www.oilshell.org/blog/2019/12/22.html#eggex
- antpls 6y agoThat would definitely help code reviews and maintenance. Is there anything similar for Python?
- 6gvONxR4sf7o 6y agoregex suffers from the same problem that inlined code does. For example, if you saw this in a code review, what would you say: log_and_return(rank_by_time(compute_recommendations(get_data(client_id,date), find_nearest_neighbors(client_id)))) You'd tell them to create some intermediate variables. But when it's a regex, apparently we're all fine with this: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_])?\??(?:[-\+=&;%@.\w_])#?(?:[\w]*))?)/
- flying_sheep 6y agoThat really depends on how complicate the regular expression is. For me this debate sounds like arguing assembly vs C. We will need some sort of abstraction to develop a higher-level stuff in case we need it.
- a_e_k 6y agoEmacs has had an Emacs Lisp version of this for a long time. It's implemented as a macro so it can build the string regexp at compile time. https://www.gnu.org/software/emacs/manual/html_node/elisp/Rx-Notation.html https://www.gnu.org/software/emacs/manual/html_node/elisp/Rx...
- jehna1 6y agoAnyone looking for a non-Java implementation: This library has been ported to 30+ languages, and you can find a list of them at http://verbalexpressions.github.io/ http://verbalexpressions.github.io/
- swlkr 6y agoIt's semi-related, but if you're into easier regex, have a look at janet's PEGs https://janet-lang.org/docs/peg.html https://janet-lang.org/docs/peg.html
- jacobwilliamroy 6y agoHow do I learn regex? I get confused because it seems like maybe there's more than one kind of regex floating around out there, and since regex is made of lots of punctuation symbols, it's very hard to search for things about it on the web. Is there a single book I can read? A couple books? Does it depend on my runtime environment?
- jug 6y agoI'm not sure if this is great or crazy! I try to not be swayed by the handpicked examples because this at least _feels_ like a design that could get messy once you try to do the particularly gnarly regexeps that this library claims it was designed for. If it's great, it should already have been done long ago, hmm...
- tekknolagi 6y agoA buddy of mine made Remake (https://docs.rs/remake/0.1.0/remake/ https://docs.rs/remake/0.1.0/remake/) with this kind of thing in mind. It's a DSL for composing regular expressions in a readable way.
- rendall 6y agoThis project seems to be rediscovered every so often https://news.ycombinator.com/from?site=github.com/verbalexpressions https://news.ycombinator.com/from?site=github.com/verbalexpr...
- skocznymroczny 6y agoLooks interesting. I find out all my regexes are pretty much write-only. When I come back to them few months later, I can't make much of them and it's easier for me to start from scratch. Tools such as https://regex101.com/ https://regex101.com/ are amazing though for development of regexes and later trying to make sense of them.
- cutler 6y agoMaybe if Java left the Stone Age and fixed the need to escape regex metacharacters this wouldn't be necessary.
- bluepnume 6y agoI tried doing the same in JavaScript/JSX a small while back: https://medium.com/@bluepnume/writing-regex-in-jsx-without-releasing-zalgo-f1f2f91e764d https://medium.com/@bluepnume/writing-regex-in-jsx-without-r... Building regexes programmatically does seem to take a lot of the pain out of it.
- asicsp 6y agoSee also https://github.com/aloisdg/awesome-regex https://github.com/aloisdg/awesome-regex for curated collection of libraries, tools, frameworks and software. https://github.com/VerbalExpressions https://github.com/VerbalExpressions is one of the resources in this collection.
- Tainnor 6y agoIt's important to note that these are still regular expressions. They still conform to the same mathematical definition as the regular expressions we all love or hate, and in fact, the library uses regular expressions under the hood. It's basically just using new language constructs for the exact same capabilities. Now, whether you like that new syntax or not, is a matter of opinion. It is of course more type-safe and probably more approachable. That said, I find the verbosity a bit off-putting, although I chalk some of this up to Java being Java - other language implementations could be a bit nicer there. I also question the API design somewhat: regexes are inductively defined, there are a couple of primitives and a couple of operators that combine these primitives and the API doesn't make this very explicit by using the builder pattern. But ultimately, I'm more used to the way regular expressions are usually written, and for many tasks, that syntax is also more portable (e.g. regular expressions can be configuration which can be hugely useful for e.g. NLP tasks). For quick one-off text replacement tasks with very simple regexes I also think that this syntax would be way too cumbersome. Lastly, there are some people in the comments suggesting the use of parser combinators, BNF and similar formalisms / tools. Those might be an option for your use case, but they don't give you regular languages (although, sadly: regular expressions in most languages nowadays are not regular anymore). Having a regular language might be an actual requirement for whatever reason (e.g. constant memory usage).
- deleted 6y ago[deleted]
- usrusr 6y agoI might actually like something like this if it did not try to replace conventional regex syntax but aimed at making it more useful by enabling composition of smaller blocks of (conventional) regex into larger. An API like that could certainly also have an equivalent of Pattern.quote(..) for the few times what you actually do want to enter unescaped (ever tried reading regex with regex?), but it would just be a minor nice to have feature. It wouldn't even have to contain all the small blocks (like [] single char alternatives, those are best left as is), just an option to describe bigger round-brace blocks out in the java syntax where nesting is validated in compile. Lookahead, lookbehind, their negatives, capture, noncapture. Noncapture with a varargs (or builder) API of piped alternatives. You could still provoke a PatternSyntaxException by writing invalid stuff in the conventional blocks, but if the composed pattern fails checking the subpatterns should be quite helpful (if there are no backreferences)
- bmc7505 6y agoAlso available in Kotlin: https://github.com/VerbalExpressions/KotlinVerbalExpressions https://github.com/VerbalExpressions/KotlinVerbalExpressions