From: shevegen@... Date: 2019-08-05T18:16:13+00:00 Subject: [ruby-core:94152] [Ruby master Misc#16047] Reconsider impact of frozen_string_literal on dynamic strings Issue #16047 has been updated by shevegen (Robert A. Heiler). I'll comment on this, but allow me to make a few partially related/unrelated comments first. Benoit has in another discussion made a comment about having asked xyz folks about a feature/change, in regards introducing (and accessing) numbered parameters in additio to denoting the name of the variable at hand. Here in this issue, I do not want to go into the pros/cons of that other feature, but purely refer to the "popularity" part. I understand that people will be very biased in favour of what they like, and what they dislike; I am not different to this. :) (Although, perhaps it may be culture-related; japanese folks seem to not have the same "pattern" or perhaps I may not see it if they write in japanese, here on the bug tracker, I don't know - I can only see the pattern on the ruby tracker and mostly non-japanese like to complain more than japanese. At the least on the bug tracker ... :P) Anyway - what I want to say with this is that matz is the one making the decisions in regards to ruby. So ultimately this is more a discussion that has to go talk about pros/cons, in regards to features/changes of ruby, and perhaps convince matz in one way or another, rather than any "convince others"; or ask others about their opinion per se. Which is of course perfectly fine too - just that matz is the language designer of ruby, not random people all over the world. However had, you have also asked specifically about opinions, and I will provide my opinion. I noted this down before over the years, in regards to frozen strings. Personally, I find: "abc def".freeze AND "abc def".dup to be ugly in general. I think it is better to never have to use .freeze or .dup explicitely. And still have everything be as fast as possible ... :P We do, however had, have to admit that lots of people were using .freeze in the past, in particular with style such as this: FOOBAR = 'abc def ghi'.freeze I saw that in many different projects; often combined with freezing Arrays as well. I find that style very ugly, but I believe a reason why this was done is because people are so eager to want to squeeze out the maximum of ruby in regards to its performance. And this is understandable to some extent. Matz tends to say that nobody minds if ruby (or any programming language) becomes faster. :) That is also partially a goal of the ruby 3.0 3x3 approach, in regards to "make ruby 3.0 3 times as fast as ruby 2.0", at the least in regards to benchmarks listed by the optcarrot test (I think). No idea if the goal has already been reached or not, but the last time I checked it was close even without mjit; and with mjit we already know we are above the goal (if I remember correctly; but I don't want to talk about the mjit now, that is only partially related to the topic). I should like to correct you on one matter, though. You wrote: > The rationale for introducing frozen_string_literal was because > rubyists were starting to litter their code with "".freeze > for optimization, and it's ugly. Now - if I remember correctly then this was not the rationale. I think matz actually had a presentation back when frozen string literals were added. The primary reason, or at the least from what I remember, was that it leads to more efficient ruby code, e. g. in particular in regards to the typical string allocation situation - and it leads to faster execution as a consequence. Again - my memory is not great, so I may misremember, but for the most part I believe that was the main rationale; I do not remember that the rationale ever was because people would use lots of .freeze in their code base. For example, I never did use .freeze in my own code bases, mostly because I hate how ugly it looks. It distracts me from other things too. :P Immutable strings are faster simply because less can be done with them. I also always said that having to use .dup and checking for as to whether a string is frozen or not, leads to more code, and also uglier code as a consequence. The various .dup additions are not very pretty to see in code. There are other ways to de-dup, such as String#- and what not, but I also don't think they are very pretty. They are mostly to be able to write less code, yet still work with immutable strings. Example: https://ruby-doc.org/core-2.6.3/String.html#method-i-2D-40 I actually use the more verbose variant here, e. g. if string.frozen? string = string.dup Not very pretty, I know, but I actually like this more than -str and +str, oddly enough. Anyway. To give you my personal opinion here: both .dup and .freeze are ugly. ;) There is, however had, one undeniable adantage - it leads to ruby scripts being executed faster, in particular for large projects. I have seen this in my own projects; although I can not give any specific benchmarks or speed improvements here, I am using ruby just about daily from the commandline, and the speed improvement IS noticable to me. So I am actually using frozen strings, even though I like oldschool string behaviour more. :P I used to add: frozen_string_literal: false to all my .rb files, but at some point I started to change it to frozen_string_literal: true. If the magic frozen comment is kept then I think it is no problem - people can just use whatever they prefer. If I remember correctly then the idea was to default to frozen strings in general for 3.0, but some time ago matz dropped this and postponed it to after ruby 3.0, due to the compatibility problem (feel free to correct me if my description of this is not accurate). > But by using frozen_string_literal we introduce the opposite > problem: we must litter the code with "".dup in order to > have mutable strings, and it's ugly. You could use frozen_string_literal: false; and you could decide to NOT use .freeze either. You are only focusing on some parts here, but not all of them. ;) There are ALWAYS trade-offs, of course. Oldschool ruby will be slower. People have to decide what they want to have; but I also don't think that inertia should affect OTHER ruby users, if they want to see changes or improvements, such as ruby scripts being interpreted in a faster way. Part of the more-than-one-way philosophy is to pick the strategy that best works for you and your use cases. By the way - you haven't yet suggested what you'd like to change specifically. :) I am also sure it would lead to some other trade-offs again. > The rationale for freezing all strings including dynamic was > because it's easy to explain I don't know from where you get these explanations of the rationales. Has matz actually said this? I am quite sure that it was not in any of his presentations, since I tend to watch these presentations. Often simpler to keep track of what is changing in ruby than reading through lots of bug tracker issues. :D I think one big reason for the magic comment was simply for compatibility, because with a hard change to defaulting to frozen strings, it would mean that lots of ruby code out there in the world would not work for new ruby releases, without them being changed. And changing all these .rb files will take ruby users quite some time. You can look at the transition phase from ruby 1.8 to ruby 2.0 and beyond. Some people are fast, others are slow. I used to be very slow in the past, and used multiple ruby versions too, but since some time I only use the latest stable (xmas release) and just keep on changing local code in .rb files whenever something changes. (I default to latest stable mostly because my heavy tinker days are over - I can always wait for the next xmas. I do, however had, also sometimes try new things in ruby-dev releases, but most of the time I just default to the latest stable.) So to come back to the transition period - having a long transition period can be good. You give people time to adjust and adapt at their own pace. IMO, this is a good thing. I still have not changed to frozen string literals to "true" for all my .rb files; only in my more important projects have I done so. For new .rb files I use ruby to autogenerate these .rb files and these files then have the proper encoding line/format, and a frozen-string true comment on top, too. > This may be true, but at the expense of making it cumbersome > to use. Yes, it is more cumbersome to use. I don't think anyone disputes this. > And also completely useless for memory optimization. I don't understand you - if we have to allocate less RAM etc... for String objects, the programs will be interpreated/evaluated more quickly, yes? To me this is a speed-related optimization. Note that I am not necessarily advocating the change as such in totality; in the past I have also commented that I don't think speed-related considerations should be the primary impetus for change regarding to ruby. I never used ruby due to speed; but there are also people who complain about ruby being "slow", so I can understand the objective to make ruby more efficient, faster etc... It's simply a trade-off situation. In the context of frozen strings, although I agree that it is uglier than in oldschool ruby, I think that it is actually worth it, due to the speed gain, which is noticable (really; someone should add some benchmarks perhaps so that people can objectively compare it, but I am sure that there is a big difference). Since the old behaviour is still there, and nobody is forced to HAVE to use .dup and .freeze in their own code base, I don't fully understand the claim that people are required to have to use either. > In my personal experience using frozen_string_literal, I find > that static strings are usually ok to freeze without changing > anything else, but that freezing dynamic strings often > create bugs that require +"" or "".dup boilerplate to > circumvent. So in the end I found myself stopping regular > use of that feature, since it's more trouble than it's worth. Yes, working with frozen strings is more annoying. Oldschool ruby were just like this: object << 'hello ' << 'world' So I do not disagree with you completely; oldschool ruby is easier to work with. But we can still control that behaviour; and I am perfectly fine using frozen strings in my .rb files, in the comment section. I don't see any problem with this. If you want the oldschool behaviour, you can just use frozen-strings to false; which should be the default right now, too. So I don't see your point, or perhaps I am not understanding you completely either. More boilerplate code is added, yes; this is not ideal either. I agree on that part. It really is a trade-off. You want faster strings? Well, then they may have to be immutable. I think python does something similar or has had a similar reasoning for having Strings be immutable by default. It's simply a trade-off. Personally I use frozen strings a lot. I found that it is perfectly possible to work with them in general and I don't have any big problem with them (but they are uglier, yes). > As such I'd like to ask other rubyists how has been their > experience with actually using frozen_string_literal on > a day-to-day basis; if my experience is unique or > common. Thank you for sharing your thoughts. I use them on a daily basis (if I write ruby code on that day). I actually almost never use .freeze, because I dislike it for some reason (hard to explain why). I have to use .dup a lot in my code, yes. Not perfect, but not the end of the world either. I guess the ideal situation would be if we could have frozen strings AND never have to use .dup or .frozen? or #- or #+. No idea if that would be even possible, though. But to conclude - I think it is ultimately a trade off that can be managed. This is just my opinion though; matz is listening to feedback from folks who use (real world use cases that is, not purely abstract ones). ---------------------------------------- Misc #16047: Reconsider impact of frozen_string_literal on dynamic strings https://bugs.ruby-lang.org/issues/16047#change-80399 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal * Assignee: ---------------------------------------- The rationale for introducing `frozen_string_literal` was because rubyists were starting to litter their code with `"".freeze` for optimization, and it's ugly. But by using frozen_string_literal we introduce the opposite problem: we must litter the code with `"".dup` in order to have mutable strings, and it's ugly. The rationale for freezing all strings including dynamic was because it's [easy to explain] (https://docs.google.com/document/u/1/d/1D0Eo5N7NE_unIySOKG9lVj_eyXf66BQPM4PKp7NvMyQ/pub) This may be true, but at the expense of making it cumbersome to use. And also completely useless for memory optimization. In my personal experience using frozen_string_literal, I find that static strings are usually ok to freeze without changing anything else, but that freezing dynamic strings often create bugs that require `+""` or `"".dup` boilerplate to circumvent. So in the end I found myself stopping regular use of that feature, since it's more trouble than it's worth. As such I'd like to ask other rubyists how has been their experience with **actually using** frozen_string_literal on a day-to-day basis; if my experience is unique or common. Thank you for sharing your thoughts. -- https://bugs.ruby-lang.org/ Unsubscribe: