by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Brian Shirai
@brixen
after working with Julia a fair bit, the value of multi-methods is obvious and undeniable
someone suggested doing these in Rubinius back around 2009-10, I should have done it immediately
the combinations of lexically scoped functions and multi-methods (multiple dispatch) is going to make very nice code
Brian Shirai
@brixen
definitely annoying to have implemented all this Encoding stuff only to rip most of it out
should have only implemented UTF-8 to start
Brian Shirai
@brixen
I wonder if I should make String immutable as a runtime option, or try to ease into immutable strings with two classes: String and ImmutableString
with the latter approach, I could make string literals ImmutableString instances now
another idea is to make MutableString and String (immutable), and when "legacy" code tries to mutate a string, do an Object#become on that instance with a new MutableString
then you could easily tag code locations that mutate String instances without breaking existing code (except if the code depends on the class being literally String)
so, in that world, something like this String < MutableString < ByteBuffer
where ByteBuffer is to accommodate IO and potentially passing through an object that has an associated "encoding" attribute, but would not be interoperable with String in process
Brian Shirai
@brixen
in other words, you could read in bytes in a particular encoding, attribute the object with that encoding instance, possibly perform transcoding on them, and then write them out
I suppose I should graphically sketch this
I need to finish implementing Object#become
Chuck Remes
@chuckremes
i like your second idea… MutableString < String (immutable) and allow String to #become MutableString
highlighting those situations at runtime then allows for fairly easy remediation to update code to be immutable-friendly
i find that so much of my new code is moving towards a hybrid of “has a” composition and functional
makes testing and reasoning about it much simpler
Brian Shirai
@brixen
@chuckremes yeah, I really like the idea of being able to fall back to mutating a string seamlessly and layer on logging or other diagnostics (eg leveraging call site types) to migrate code toward full immutable strings
thinking more about ByteBuffer, I'm not going to have that in the String hierarchy because I don't want those to be inter-operable
Brian Shirai
@brixen
essentially, there are two ways to transport bytes through a process:
  1. at the IO boundary, transcode from whatever-in to UTF-8, and then transcode from UTF-8 to whatever-out;
  2. at the IO boundary, read whatever-in, tag it with whatever, and then later be able to encode to UTF-8 when #to_s ing it, or write it back out, possibly transcoding it before or when writing it out
Brian Shirai
@brixen
#1 is String, #2 is ByteBuffer
Brian Shirai
@brixen
hm, in fact, ByteBuffer won't have a #to_s or #to_str method on it
rather, String will have a constructor that takes a ByteBuffer
Brian Shirai
@brixen
I think I can use ByteBuffer to work on the new register instructions for indexed objects (eg byte[])
looking at how to introduce attributes to classes
of course, the Ruby-ish way would be a class method, something like:
class A
  # Option 1: this permits various options for a specific attribute
  attributes immutable: true, concurrent: true

  # Option 2: this presumes all attributes are boolean
  attributes :immutable, :concurrent

  # Option 3: mix 1 & 2
  attributes :immutable, concurrent: [:read, :write]
end
Brian Shirai
@brixen
but I was thinking about something slightly different, like this:
# the 'method' scoping A would be a compiler pragma
class attributes(:immutable, :concurrent)::A
end

# this works with arbitrary class paths by inserting before the class or module being created
class A::B::attributes(:immutable)::C
end
this would allow "accumulating" attributes as classes are re-opened, but would not be able to unset attributes (eg immutable) that disallow it
it would be an interesting way to, for example, re-open Array in your program and add concurrent attribute
either syntax could allow this actually, but the 2nd form allows the compiler to know this before any code executes in the class/module body, which probably has advantages
also, this would avoid any name clashes because the attribute identifier wouldn't be in any identifier scope (eg variable, method)
Brian Shirai
@brixen
@chuckremes @ljulliar thoughts on that?
hmm, I could use the same mechanism to create a way to make data types, but the syntax would be a little weird:
class type()::V
  x: int
  y: int

  fun norm()
    sqrt(x**2 + y**2)
  end
end
Brian Shirai
@brixen
maybe I really should start that way because making data or type a keyword is gonna break lots of stuff :frowning:
Laurent Julliard
@ljulliar
Like @chuckremes I like the idea of a String possibly becoming mutable (btw I don't know if it's relevant in any way here but I think I read that in the last release of Rudt they tried to relax somehow the way variables can become mutable). There has to be some flexibility here. As for the syntax I personally far prefer the use of attributes which btw is ablso amenable to other evolution like static type declaration without having to change the syntax of Ruby. Like in attr_type my_attr: :String, my_other_attr: :Circle. This is what I opted for in Rlang.
Brian Shirai
@brixen
@ljulliar which attributes, the module method or the compiler pragma in the constant path?
also, not sure if you saw my examples for types in the README, but thoughts on that?
Laurent Julliard
@ljulliar
I meant the module methods
Brian Shirai
@brixen
ah yeah, they are very Ruby-ish, but easy to conflict with other code and there's no restrictions on where they are placed, which means you could start defining methods that have mutating bytecodes and then say attributes :immutable, for example
leaning more towards compiler pragmas, but I haven't implemented anything yet
Ruby doesn't have syntax for decorators but the path "method"-like syntax would function something like a decorator
what I really need to do is finish the PEG instructions and get started on a new parser
couple great videos, one very old, one brand new...
Laurent Julliard
@ljulliar
@brixen you are right: those statements are position depedent. I agree that this is quite unusual in Ruby but it is already the case for statements such as public and private that are also position dependent. One of the other advantage of this approach is that you can easily make it backward compatible by defining module methods possibly fake ones doing nothing by the way and keep your code running in older non-typed version of Ruby
Brian Shirai
@brixen
that’s the beauty of those compiler pragmas, they are normal syntax and could be no-op methods
So everything is equivalent for those considerations
Laurent Julliard
@ljulliar
Ah yes. That's right.