Hacker News new | past | comments | ask | show | jobs | submit login
Ruby 2.6 (martinezgomez.name)
299 points by merk_ on Dec 24, 2018 | hide | past | favorite | 159 comments



I am always happy to unwrap my Christmas present from the Ruby team! Some questions about this release:

- Are there any benchmarks for the new JIT?

- Why was `(Date.today..(Date.today + 1)) === DateTime.now #=> true` false in Ruby 2.5? It seems correct that right now is between today and tomorrow. Is it because one is a Date and the other a DateTime?


About your question, the reason is that `===` is aliased to `Range#include?` which checks if the argument is a discrete element contained in the range.

That range of `Date`s does not include any `DateTime`s, so the inclusion check returns false.

`Range#cover?` on the other hand, just uses >= and <= to check .


> Are there any benchmarks for the new JIT?

From the horse's mouth:

"...apparently JIT on Ruby 2.6 failed to be ready for production." [1]

[1] https://medium.com/@k0kubun/ruby-2-6-jit-progress-and-future...


fwiw https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Some of those Ruby 2.6 programs are faster with --jit and others are faster without --jit

faster or similar: nbody #2, fasta #6, fannkuchredux #2, spectralnorm #4

slower with --jit: binarytrees #5, pidigits #5, regexredux #3, revcomp #5, mandelbrot #2, knucleotide #1


Benchmarks here: https://medium.com/@k0kubun/ruby-2-6-jit-progress-and-future...

tl;dr: your Rails app is not faster with this feature in this version, but might be in the future.


Been a while since I’ve used any Ruby but isn’t the first expression a range where’s the second a single value?

It’d be like [0,1] === 0


> isn’t the first expression a range where’s the second a single value?

`===` conventionally means 'matches', or 'includes', so an aggregate on the LHS and a scalar on the RHS is typical.

It isn't defined for `Array` beyond being the default of equality - I don't know why - but it is defined for `Range`.


[flagged]


Note that you would almost never use the === directly - usually it is done by invoking a case statement, so it would be like

  case DateTime.now
  when Date.today..(Date.today + 1)
    .. do something
  else
    .. or not
  end


Sorry - this is pasted out of the article, and refers to a change in the semantics of the === operator for Ranges.


Fantastic Christmas present from the Ruby team.

Ruby is alive and well despite all the rumors of it's demise. I predict a resurgence in its use over the next few years.

Can't wait to examine and try out the new features.


What makes you think there'll be a resurgence in its use in the next few years?


Ruby used to be my most beloved language. I've since developed a strong appreciation for good type system. However, working with collections of any kind in Ruby is just such a joy. The methods around it are so well thought throug and make writing code a joy that in most other languages just would be tedious. On top of that the Ruby team is constantly working on making that aspect even better. I truly don't understand why it seems to me that no other language I use makes even an effort to provide something similar. Getting a map, a reduce and a filter function seems to be as far as most standard libraries are willing to go.


Try Crystal and you get the joy of Ruby enumerables together with a static type system.


Crystal is nice, but my love affair with Swift is going strong. Not exactly Ruby syntax but pretty similar in terms of simplicity. I am a Rubyist who feels right at home with Swift. But for the new year, I definitely want to give Crystal a fair shot!


Kotlin is my new love. Best collections library of any language I've used, great type system, coroutines are amazing, and all of it integrates perfectly with 25 years of rock-solid Java libraries.


While the collections library may be better than others, it has a great many warts, many of which aren't discoverable until you've used it a long time. Some of these warts are a result of JVM interop requirements. It's not just the collections library, while the language is great and better than others, there are mounds of bugs and poor design decisions.


What do you use Coroutines in a static language like Java, for ?


Everywhere I used to use CompleteableFutures, except without ending up with completely unmaintainable code.

https://github.com/Kotlin/kotlinx.coroutines/blob/master/cor...


Very interesting, thanks!


Interesting. What’s your opinions on Crystal right now as a substitute for Ruby? Is there a good stack like Rails for Crystal?


Take a look at Lucky framework!

https://luckyframework.org


Quite immature, especially when it comes to community and library support.

But dang it's nice to do stuff in it.


Crystal is definitely not production ready, I mean a language without thread support...


Yeah, it’s only now MT schedulers is work in progress to bring multithread fibers to Crystal

https://github.com/crystal-lang/crystal/pull/7214


Thread support in interpreted languages isn’t that parallel to begin with.


JRuby threads are fully parallel and in production use today. CRuby's GIL is an implementation choice rather a property of dynamic/interpreted languages.


Is it really a "choice" if the alternative is really hard to achieve in practice? It's like calling python's GIL a choice... with numerous projects trying to get rid of it in various ways and never really succeeding to do it while keeping the single threaded performance and the extensions API.


It is a choice to keep backwards compatibility with the C extensions API.

The GIL would be quite easy to replace otherwise.


> It is a choice to keep backwards compatibility with the C extensions API.

IIUC for CRuby it's mostly about how to keep the VM simple. Koichi Sasada is working on an ownership based model like Erlang has, which sidesteps a bunch of theses issues.


I’m wondering.. what is the effect of letting the JVM handle synchronization then ? Wouldn’t they still need to synchronize within JvM ?


Try Kotlin and its collections.

I used to love Ruby too but the dynamic typing quickly became a deal breaker. So I set out to find a language that's as pleasant to use on a daily basis, with well designed libraries and collections, but also statically typed.

Kotlin met all these requirements for me.


You should try smalltalk :)


My thoughts exactly. I feel it isn’t the library, but the grammar, which is why the same feel cannot be replicated by other languages. Ruby is just easy on collections.


Can you comment on why a good type system became so important to you? I can understand the value in interfaces but not really in any other context.


Not having `nil` is soooo nice. I can't count the number of `Runtime Error`s because some method isn't defined on `NilClass` that have blown things up in weird edge cases.

Knowing exactly what types a method takes and the compiler catching incorrect uses before the code ever runs saves a lot of frustration. Another thing I've enjoyed in Rust include `match` clauses forcing me to define branches for any possibility, especially for `Result` structs. In ruby this isn't possible because anything can be anything.


There's got to be more to it than "has / doesn't have nil". Lisp has nil, and I rarely if ever see an analogous error there, or even a type error.

I have a hunch that single/static dispatch is what tends to cause more problems than merely the presence of nil. It's not nil, but how you use it.


"It's not nil, but how you use it."

Can you elaborate on how multi-dispatch reduces the issue of nil/null?

I also use static type (typescript) to prevent issues with nil and would like to know how I can achieve the same in a dynamic language.


You can prevent nil errors using contracts like in Eiffel and Clojure.


I can't type up a full answer right now, but for me, a strong type system is about being able to model my domain and bake all of my assumptions about that domain into the types I define.

It's a lot easier for me to reason about and avoid edge cases when I can (more or less) verify at compile time that invalid states are impossible.

This is about more than just catching null values, and also encompasses things like mutually exclusive fields, and access control.

If you're interested, I gave a talk once that dives into these ideas more effectively than I can express in this comment: https://github.com/ShaneWilton/programming-with-types-talk/b...


For a non-strong-typed language, it's difficult to dive into the code after you haven't work on that codebase for a while.

We were on a really old Mongoid (or carrierwave, or some other gem, can't remember), It was difficult to find the right methods to use and etc.

I understand it was our own fault not to write comprehensive tests or keep all gems up-to-date.

But a dynamic typing language is a lot more "punitive" when we aren't writing perfect code, using perfect design, and/or exercising perfect engineering practices.


Languages without ADTs and Optionals just feel impoverished.


Languages without full blown union types feel so impoverished. With good language typing support (including flow typing), optionals feel quite redundant.


But optionals are just a union type (T | None).


Languages without dependent types feel that something is still missing.


Fewer run time errors. Easier testing, among other things.


The === for Range and Datetime serves as a one example, with a good type system they wouldn't be directly comparable.


what bout clojure?


Clojure's stdlib is unintuitive, and `into` is the poster child.

It's easy to find what's available in Ruby: https://ruby-doc.org/core-2.5.3/Enumerable.html

Good luck with Clojure: https://clojure.github.io/clojure/clojure.core-api.html


https://clojuredocs.org/ is what I always used. I dislike ruby's docs actually. Rust and Crystal have better UX design for their docs.



I'm talking about the flat namespace.


While I understand the sentiment that all the functions aren't necessarily grouped as in OO languages, I think the Clojure functions are harder to group because they're more general. That's not necessarily the strongest argument, but it is so much more obvious in OO because you always have the object to group by compared to functional languages.


Oh boy, you are in for some treat if you try Clojure. But be warned, love for Ruby will be gone.


Can you recommend a post/article explaining some of what makes Ruby's collections especially pleasant? Studying Ruby's stdlib design has been on my 'someday' list, but there's so much else there...


It's mostly how complete the API is and how consistent. For example: * Hash#merge takes a block for conflict resolution. I use this all the time for aggregating counts. * #sample * #unique * Everything has a change in place option by appending "!"


Also, chaining is extremely concise. e.g. "products.map(&:cost).sort.last"


I couldn't resist...

Your example could be improved by using "products.sort_by(&:cost).last"

I try to not use map because often there are methods that already implement filtering. Gotta love Ruby readability.


I think you need `products.sort_by(&:cost).last.cost` for the same result.


You’re correct!


one beautiful design decision ruby made really on was that every method would have the option to take a block of code when it was invoked. the code block gets passed to the method as a closure. this makes writing collection apis very pleasant, since so many of them involve passing in a single closure to operate on each element.


Groovy. Probably because Groovy borrowed quite a lot from Ruby.


Apache Groovy even borrowed its name from Ruby -- it's really Gruby, if you get what I mean. And of course Grails started off as a clone of Rails.


Definitely. I dabbled in Ruby but kept coming back to Groovy because it had all the nice syntax of Ruby but all the advantages of the JVM, solid Java ecosystem / libraries and optional strong / static typing to apply when valuable (eg: defining interfaces or data types).


The only collection I wish Ruby improved upon is a simple Lisp style linked list. Kind of amazed JS has an easier way to do cdr than Ruby:

    const list = [ 1, 3, 4, 2, 8, 5];
    const [fst, ...snd] = list;
But I suppose that's just a result of JS implementing pseudo-pattern matching.


    head, *tail = *list
Has worked since 1.8. Don't ask me how I know that :-P


Damn, I should have remembered that. Especially considering I had a project where I had to trawl through the ruby parser including multiple assignment rules.


To be fair, I find the destructuring syntax strange in Ruby. For example, why do I need the splat on the list? It doesn't make sense to me. I'm sure there is a good reason buried in the implementation, but if I were to design the syntax, I don't think I would do it that way.


> For example, why do I need the splat on the list?

You don't on the RHS, or rather, it's redundant in the given example. On the LHS you need it to prevent single element capture.. and within the ruby language, it's a fairly consistent sigil.


Wow. You're right. I'm not sure how I got that wrong. I'm sure I tried it. Thanks for correcting me!


There's always Elixir :)


How is this different than splatting (my lisp is not so great.)?

https://repl.it/repls/EcstaticLamePaint


This will be fun. I’m glad we now have some performance improvements to some common methods. For those considering playing with Ruby, you should! One thing I’m surprised not many has mentioned what makes ruby unique and awesome, BLOCKS!


> what makes ruby unique and awesome, BLOCKS!

Similar to blocks in Smalltalk and Self, surely?

Still, having worked with ruby a fair bit the past year, it does deliver much of what Smalltalk does (not surprising, as ruby borrows heavily from smalltalk).

https://www.gnu.org/software/smalltalk/manual/html_node/Invo...


Scala and Kotlin let you achieve something similar, without requiring a dedicated `yield` keyword, as well as not introducing yet another type of function into the language... Personally, I always found the number of different types of function in Ruby to be bewildering.

Scala even allows multiple blocks to be passed in, used to good effect in the Cats effect `bracket` function, amongst others.


I'm not so sure about the block thing. I mean I like having first class function-like objects, but you've got blocks and procs and both of these are different from bound and unbound methods. I would prefer that there was a single function type, personally. I wonder if I'm missing something, though. Is there an advantage to distinction between blocks and procs that ruby makes?


A block is a proc.

```ruby

def foo &bar

  return bar
end

foo {}

# => #<Proc:0x00007ff23783c4e0@(irb):16>

```

But I do agree that I don't quite understand the need for the distinction between procs and methods, or the need for unbound methods; I would think that methods could just be either bound to one object or another, as unbound methods are useless for the fact that they won't work at all unless they are bound.


I think they rather meant the difference between procs and lambdas (e.g. wrt return).


I love ruby, but I kind of consider blocks an antifeature compared to, say, JavaScript arrow functions (where you can actually call return and not inanvertsntly break out of the entire enclosing function).


Aren't they like arrow functions in JavaScript?


A lot of this kind of stuff is more about language and standard lib culture than strict language features. Ex - Rust actually has exceptions, technically, in the form of Panics, and you can infact catch them. But the culture of Rust is strongly against using panics in that way. Basically never catch panics and only allow them to happen when you're okay with the whole program blowing up. Use Option and Result and check them if you care about your program not blowing up.

Similarly, Ruby has nice blocks, and many other languages have similar closure support. But Ruby's support is so built-in from day 1 and heavily used in the standard library and the general culture of Ruby gems. Many of the methods in Enumerable take blocks, making it easy to chain a bunch of functional stuff together, even without any support gems and from the earliest days of Ruby.


Just parameters that are functions, except that you can only have one per function. I still fail to see the advantage of blocks over being able to pass functions as arguments like in other languages.


One nice feature of blocks is that `return` will return from the enclosing function, rather than the block, so you can write:

    def find(x, l)
      l.each do |y|
        return y if y == x
      end
    end
Where in Lisp you'd use (return-from find x) and in other languages you might pass in a continuation or use a special return value protocol. It's a nice solution for higher order functions that are supposed to feel more language-level.

Also, you can pass functions as arguments like in other languages; lambdas behave like you would expect them to.


Blocks are essentially just anonymous functions.


Really like the idea of using lazy ranges instead of magic negative indices! I.e `xs[6..]` instead of `xs[6..-1]`.


Negative indices aren't magic. They follow the obvious wraparound (modular) pattern: Negative `i` indexes the element in array `a` located at `i % len(a)`. If they worked any other way it'd be madness.


True, they're not magic, it just looks ugly for the most common case of fetching to the end of the array. The new syntax is much nicer than -1.


I don't think you got that index calculation right. -1 in array of 5 elements is located at 5-1 == 4, not at 1%5 == 1.


It depends on how you define the modulo operator [0]--there are definitions where (-1)%5 == 4 and definitions where (-1)%5 == -1. Presumably the GP is referring to the former case.

[0]: https://en.wikipedia.org/wiki/Modulo_operation#Remainder_cal...


I don't follow your point. We're concerned with the value of -1 % 5, not 1 % 5. There's no definition of the modulus operator on which -1 % 5 = 1.


Phrasing issue, I think. I understood "Negative `i` indexes the element" as `i` itself being positive. Like you'd say "negative 1 indexes" (i is 1), not "negative -1 indexes" (i is -1)


> Constant names can now start with non-ASCII capital letters. I am not sure how useful this is

Very? If you want to code in non-Latin languages.

Also, π = 3.14159


I'm not sure about this being good for coding in non-latin. It might actually encourage behavior to mistreat ruby constants as regular variables. IIRC constants are not really constant, but only visual help for reading code and ruby just issues a warning on reassignment and these warnings are not shown by default.

I can totally imagine new devs just trying out non-ascii variables, see it not crashing and then actually writing all their code using constants.


> I can totally imagine new devs just trying out non-ascii variables, see it not crashing and then actually writing all their code using constants.

Ruby already supported non-ascii identifiers for variables; 2.6 added support for non-ascii first characters of constants, which must still be capital letters, as had always distinguished constants from variables. It doesn't make anything non-ascii a constant, it just makes constants consistent with other identifiers in terms of non-ascii support, while preserving the “initial capital means constant" rule.

And, as sibling comments note, reassigning a constant produces a warning, so devs making a mistake and using constants for variables (regardless of ascii-ness) will quickly be informed of their error.


I wasn't aware of non-ascii variables. I was thinking about UTF support for Japanese characters, when I read the change. There is no concept of lowercase/uppercase. 日本語 is this a constant or variable?


Since constants are the exception, and used to require an ASCII capital but now can start with ant capital, an identifiers starting with a Unicode character in a script that doesn't have upper/lower case distinction is a variable, not a constant.


I don't quite understand how this change makes the (somewhat remote) misunderstanding you describe any more likely than it previously was for people using ASCII only.

I also just tried and was duly warned upon reassignment, a setting I don't remember changing.


Re-assignment warns by default. I tried it, exploring to see what was possible. It indeed worked but threw a warning. I hadn't changed configuration.


Looks like an ‘n’ at first glance. Just as easy to type “pi”.


Is it a good time to learn Ruby? I mostly do React and Node + Java work professionally, but I've been looking into Ruby as a fun side project language. I would appreciate any anecdotes!


Depends what you want to do, 90% of what I code in is python or Ruby, and I'll switch to C when I want performance. I've done a lot of rails (Ruby), Django (python), and flask (python) work in web development. Much prefer rails, eaiser, and better thought out. I have several websites with hundreds of thousands of visits a year, it is fine (all the frameworks are). I have had to do some inline C to speed up my Ruby in a couple of instances - but that's very specific (and something you can easily do).

In terms of data science, python is my go-to and much more tooled for that kind of work. For any kind of desktop app I'll use C++, and for browser extensions / add-ons it's JavaScript.


You should give crystal a go for the parts you need to be performant! You can even prototype those parts in ruby and easily convert to crystal when it becomes necessary. We’ve found a really nice balance, with business logic and interfaces in Ruby/Rails and crystal for AI/data processing.


Oooh, that sounds interesting. Where would be a good place to start with Crystal assuming I specifically want to use it for AI/data processing with Rails business logic / interfaces?


Crystal usage in actual Production ? Any pitfalls?


Ruby isn't perfect but it's a great utility language and can do a lot of powerful things with very little effort. Read through Eloquent Ruby

The only problems I wouldn't go to Ruby for are CPU intensive ones or ones where I need parallel threads (which you already have Java for)


You can also use JRuby. Powerful and can be very easy to the user.


Had a problem that I'd typically use Ruby for but needed to shed the GIL. JRuby worked beautifully. The only gotcha was I needed to use the JDBC driver for Sequel instead of the usual drivers. Obvious in hindsight but not so much with zero JVM development experience. I'd use it again.



From the Truffle readme:

> TruffleRuby is progressing fast but is currently probably not ready for you to try running your full Ruby application on. However it is ready for experimentation and curious end-users to try on their gems and smaller applications.

> TruffleRuby runs Rails, and passes the majority of the Rails test suite. But it is missing support for Nokogiri and ActiveRecord database drivers which makes it not practical to run real Rails applications at the moment.

Emphasis mine, but that puts it firmly in the "fun toy" category rather than a viable technology for anything mission critical.


> Emphasis mine

Do we think that's what `jb3689` meant by CPU intensive.


I am a big fan of Ruby. The syntax and stdlib let you write code that is very close to a natural English sentence. For example, Ruby has both `if` and `unless`, so you can express a condition as `unless condition` instead of `if !condition`. And the frankly great Enumerable module provides a great collections API, miles ahead of Java in particular. If you're sick of writing for-loops I recommend giving Ruby a try!


It a language made to make you as a developer happy. So, yes.


Ruby is awesome for prototyping. It's just incredibly fast to work with, because the language makes an effort to provide as much help as possible and adding as little obstacles as necessary. E.g. you can even add/change functions to/of Object, even during runtime, if you think it helps. Rails adds `blank?` like that, which is a helper for `nil? || empty?`.


As good as any time. You will loose a lot of performance when compared to v8 but the ruby paradigm is subjectively much more pleasant to work with.


Enumerable methods are almos always what make me want to ditch Javascript for Ruby.


ES6 has map, filter, reduce, etc... and anonymous functions which can be used in lieu of Ruby blocks.


Have a look at:

https://ramdajs.com/


As a Ruby dev on the hiring market until recently Ruby seems to be in kind of the same spot as Perl some time ago: many new/existing Ruby/Rails projects are around, so it's kind of mainstream but not as much as PHP/Node/Java/whatever is which means less job offers, yet not quite niche neither, and there seems to be kind of a slight lack of Ruby devs around, and it can act as a differentiator, even for non-Ruby jobs. There's quite an interesting market dynamic at play here.


Is it a good time to learn Ruby? I mostly do React and Node + Java work professionally

It can be fun and it's as close as Smalltalk will probably get to mainstream acceptance, but if you are hoping for a lucrative commercial skill then probably you have missed the boat. Ruby is mainly used for two what most would now consider legacy things, Rails based websites and Chef based infrastructure. There is still some money to be made in maintenance of course and will be for a few years but the sun is definitely setting on Ruby. But 10 years ago it was super-hot.


For me it is too much fun. I love that I can use most of the standard library without thinking / looking at the documentation, and not needing to wait for compilation.

But at the same time I hate that I love a language that performs so bad compared to being closer to the metal.


Have you looked at crystal (https://crystal-lang.org/) ? Very ruby-like, but has additional safeties and compiles to native.


It looks fun, but as I'm doing financial modelling right now, Julia may be a better fit for me, as it has very nice libraries as well.


You may want to check APL family as a possible option for prototyping at least.


APL itself looks really really bad language with bad documentation, no real libraries, non-existent type system, bad function names, and I don't see any GPU programming support in it. In the family Matlab is still the best (It can do Monte Carlo simulation on the GPU, and has a great library for different distributions), but it's still much slower language than Julia generally.


What use cases do you have that are more performant in other languages?


Right now I'm working on financial time series modelling. I can't use numerical arrays because the model is not parallelizable. Also R / Mathematica are not good for these kind of stuff.

I'm thinking of trying out Julia, as it's dynamic but still has a lot of interesting libraries, but for now I just decided with working with small data, so actually I don't have performance problems.


It is as good time as to, say, learn Farsi. It's beautiful, it's fun, learning it is a great experience, and, plus, quite a few people already enjoy speaking it. Or, you could learn something else without feeling much of a loss.


Almost has nothing to do with learning Farsi, great analogy otherwise


It’s a good time to learn any language if it has any popularity at all.


The access to AST will allow for neat hacks like PonyORM on Python, which could be a way for me to improve Rebel::SQL. Tentative hacks by decompiling bytecodes or using Parser, while fun, proved practically unsatisfactory.

https://ponyorm.com

https://gitlab.com/lloeki/rebel


What is the complexity of set operations on arrays? This seems a bit too much sugar to me, to the point where people will end up writing inefficient code because they will thing these methods are more performant than they really are. Usually, I like to see explicit conversions to sets to make the performance characteristics explicit.


In most real world applications, the cost of doing an in-memory data manipulation like this is negligible compared to I/O, waiting for the database etc. It's already the wrong language for someone who wants to squeeze out every CPU cycle, and imo it's a Good Thing for a language upgrade to embrace its strengths ie syntax sugar in the case of Ruby, as long as the perf hit isn't out of control.

I'd agree developers should pick the right data structure for the job and some APIs can obscure the cost to the point of misleading developers into woefully wrong decisions. I just don't think it's the case with array ops like union as it's easy enough to handle them efficiently. I too would be interested to see any benchmarks though.


I might be more receptive to this if this was added to all collections, then, rather than just arrays. (Maybe it was? I don’t write Ruby, so I don’t know for sure. Maybe Ruby doesn’t have a generic “collection” protocol?)


Interesting point. Ruby has an Enumerable module, but these methods were added only to Array. Since the main native collections (Set/Hash/Array) all support them now, they could probably be added to Enumerable in the future, with class-specific optimizations if necessary.


> This seems a bit too much sugar to me, to the point where people will end up writing inefficient code because they will thing these methods are more performant than they really are.

Real-world performance and asymptotic complexity aren't the same thing.

> Usually, I like to see explicit conversions to sets to make the performance characteristics explicit.

The performance problem with this approach (for certain problems) when you have input arrays and want an output array is that Array->Set and Set->Array conversions are not free, and even if this is better in asymptotic complexity, you aren't always operating at the extends where asymptotic complexity dominates, so you can end up with code that is both excessively verbose and unnecessarily nonperformant just to make asymptotic complexity more apparent.


Typically, they will be linear on the combined size of the arrays. - for example is implemented by putting all elements of the right side in a hash map and then iterating through the first one and deleting all that can be found in the hash.


I haven't used Ruby before but I'd have to guess that their Array implementation utilities table doubling, if this is the case operations like concat, union, and difference should be linear.


one shot mode [1] for coverage will be handy in production as it has quite no overhead. Happy xmas Ruby devs!

[1] https://bugs.ruby-lang.org/issues/15022


I was trying to go download the latest Ruby or even read the latest release notes, but the site seems to be down. It's still ruby-lang.org, right?


Weird. I googled "ruby 2.6 download" and links from the results worked, but simply trying to browse to "ruby-lang.org" times out.


It just resolved for me. Maybe it'll clear up for you soon!


Am I the only one to find -rcX and -previewX type of versioning confusing. like how much time is remaining etc.


For when Ruby 3.x?

They should release soon, if we are to start seeing some decent adoption by 2028.

/pythonicsarcasm


> non-ASCII constant names

This is actually a security risk, avoiding all Unicode security recommendations. See e.g. http://websec.github.io/unicode-security-guide/visual-spoofi...

All they did was open the floodgates: https://github.com/ruby/ruby/commit/f852af0e59899157ef695edc...

no rtl checks, no spoofing, no mixed script checks, no normalization.


For URLs sure. I can’t see the problem for internal constants...


Identifiers are named identifiers to be identifiable. Unicode spoofs are not identifiable anymore. It's not rockets science.

Every name needs to be identifiable. Simply enabling XID_Start + XID_Continue for unicode violates all unicode security recommendations. See the recommended Unicode Security Profiles 1-5, http://www.unicode.org/reports/tr39/#General_Security_Profil...

ruby violates all of them. so do many other languages.

BTW identifiers are not just url's, mail addresses or variable names, but also usernames and paths (filenames, directory names). eg with RTL spoofing you can hide ../

nobody cares so far, esp. not Linux filesystems. Garbage in garbage out is a security risk. The old Apple HPFS at least normalized unicode, the new one is again insecure.


How is it it a security risk to name a constant in source code?


it can be used to create malicious pull requests that are visually indistinguishable from correct ones


> it can be used to create malicious pull requests that are visually indistinguishable from correct ones

If your only check on the correctness of submitted code is visual inspection, you've got a much bigger problem than Unicode confusability.


How do you check your code? Presumably, you’re not able to exercise the full range of inputs, so at some point you will have to look at the code and figure out what it is doing…


Which means you'd notice the value of a constant being exfiltrated, since a maliciously named constant doesn't magically expose secrets outside of the application.


I suggest you take a look at some of the submissions in e.g. the Underhanded C Contest. Where it can be excruciatingly hard to figure out where the backdoor is even though you know that the code has one.


Do you apply formal verification to your codebases to make sure there are to cleverly-crafted backdoors that still pass all the unit tests? Would be interesting to hear about.


In Ruby it can easily be used to submit malicious source code to a repository (for example the reviewers thinking that a variable is set to some value, when in fact a new variable is created).


An attacker would still have to _do_ something with their new maliciously named constant, which would be as noticeable as any other malicious contribution. This is grasping at straws.


This is probably pretty overblown, but if a function takes a flag, it would be possible to pass in a different value to the function than appears to be passed in at first glance.


Not really, just thinking that an operation changes a variable when it in fact doesn't is enough to introduce a security vulnerability.


He linked a resource that explains visual spoofing, an "attack technique" in which an attacker registers a domain that renders exaclty the same as yours, but actually isn't (because it uses unicode points which render the same --or very similar-- to latin alphabet letters).

I woulnd't go as far as saying "it's a security risk", but on some situations it may lead to weird bugs in which you think you're referring to one constant/variable and you're actually referring to another (visually equivalent/the same) const/var.


I only skimmed over the linked resource, but non of the mentioned attack vectors and issues seem to be a problem for variable names in source code?


It enhances risks if you are doing things that are already risky, like using Ruby's dynamic facilities to either expose the user to things based on names in source (“eval” of user-submitted content, or things dynamically constructed from it, for example.)

But I can't see much else that is a realistic security risk (readability and code clarity risks are another story.)




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: