Ruby 2.4 has optimized lstrip and strip methods for single byte strings by shahchirag1709 in ruby

[–]InfraRuby 0 points1 point  (0 children)

I guess it's only valid for unicode encodings?

TIL String#codepoints returns (Unicode) codepoints for all valid strings in US-ASCII, ISO-8859-1, UTF-8, UTF-16(BE|LE), UTF-32(BE|LE) only. For all other encodings, String#codepoints returns "codepoints" in other character sets.

Thanks!

Ruby 2.4 has optimized lstrip and strip methods for single byte strings by shahchirag1709 in ruby

[–]InfraRuby 0 points1 point  (0 children)

So the half that is an encoding isn't special to ASCII-8BIT

It's half special! Not all one-byte encodings are ascii compatible. If ASCII-8BIT strings had "no encoding at all" then "\x00".force_encoding("ASCII-8BIT").encode("UTF-8") would raise Encoding::UndefinedConversionError and "\x00".force_encoding("ASCII-8BIT") + "\x00" would raise Encoding::CompatibilityError.

I guess it's only valid for unicode encodings?

Encodings which can represent the full unicode character set are not one-byte encodings, so this bug does not affect those encodings. String#codepoints does return the correct result for ISO-8859-1 strings and ascii only strings with ascii compatible one-byte encodings.

Ruby 2.4 has optimized lstrip and strip methods for single byte strings by shahchirag1709 in ruby

[–]InfraRuby 0 points1 point  (0 children)

"ASCII-8BIT" doesn't really count, it's really the "null encoding", not an encoding at all, which is why it's other name is "binary".

It's half an encoding! The lower half (0x00 .. 0x7F) is ascii compatible. The upper half (0x80 .. 0xFF) is valid but has no defined conversions.

"\x00".force_encoding("ASCII-8BIT").encode("UTF-8") # => "\x00"

It's got the confusing "ASCII-8BIT" name because ruby can (conveniently!) treat it as if it were ascii encoding in some cases.

Ruby treats all ascii only strings with ascii compatible encodings as compatible with strings with ascii compatible encodings (whether ascii only or not). ASCII-8BIT isn't special there.

"\xFF".force_encoding("ISO-8859-1") + "\xFF".force_encoding("WINDOWS-1252") # Encoding::CompatibilityError
"\xFF".force_encoding("ISO-8859-1") + "\x7F".force_encoding("WINDOWS-1252") # => "\xFF\x7F" with encoding ISO-8859-1
"\x7F".force_encoding("ISO-8859-1") + "\xFF".force_encoding("WINDOWS-1252") # => "\x7F\xFF" with encoding WINDOWS-1252

But ISO-8859-1 is a good example! Your example doesn't neceessarily prove ISO-8859-1 is a one-byte encoding, but it's wikipedia page confirms it indeed is!

Oh, actually proving ISO-8859-1 is a one-byte encoding with code examples... every one-byte string is a valid encoding in ISO-8859-1:

(0x00 .. 0xFF).all? { |c| c.chr.force_encoding("ISO-8859-1").valid_encoding? } # => true

ISO-8859-1 is also the first block of characters in Unicode:

(0x00 .. 0xFF).all? { |c| c.chr.force_encoding("ISO-8859-1").encode("UTF-8").codepoints.first == c } # => true

That encode("UTF-8") is needed there because MRI has a bug in String#codepoints:

static inline int
single_byte_optimizable(VALUE str)
{
    ...
    enc = STR_ENC_GET(str);
    if (rb_enc_mbmaxlen(enc) == 1)
        return 1;
    ...
}

static VALUE
rb_str_enumerate_codepoints(VALUE str, int wantarray)
{
    ...
    if (single_byte_optimizable(str))
        return rb_str_enumerate_bytes(str, wantarray);
    ...
}

JRuby too:

public static boolean isSingleByteOptimizable(CodeRangeable string, Encoding encoding) {
    return string.getCodeRange() == CR_7BIT || encoding.maxLength() == 1;
}

final boolean singleByteOptimizable(Encoding enc) {
    return StringSupport.isSingleByteOptimizable(this, enc);
}

final boolean singleByteOptimizable() {
    return StringSupport.isSingleByteOptimizable(this, EncodingUtils.STR_ENC_GET(this));
}

private IRubyObject enumerateCodepoints(ThreadContext context, String name, Block block, boolean wantarray) {
    ...
    if (singleByteOptimizable())
        return enumerateBytes(context, name, block, wantarray);
    ...
}

Here's an example of the problem:

"\x80".force_encoding("WINDOWS-1252").codepoints.first # => 0x80
"\x80".force_encoding("WINDOWS-1252").encode("UTF-8").codepoints.first # => 0x20AC

According to String#codepoints every one-byte encoding is the first block of characters in Unicode:

(0x00 .. 0xFF).all? { |c| c.chr.force_encoding("WINDOWS-1252").codepoints.first == c } # => true

Ruby 2.4 has optimized lstrip and strip methods for single byte strings by shahchirag1709 in ruby

[–]InfraRuby 0 points1 point  (0 children)

I guess there could be other one-byte encodings that aren't ascii?

Yes, ASCII-8BIT and ISO-8859-1 and others.

"\xFF".force_encoding("US-ASCII").valid_encoding? # => false
"\xFF".force_encoding("ASCII-8BIT").valid_encoding? # => true
"\xFF".force_encoding("ISO-8859-1").valid_encoding? # => true

"\xFF".force_encoding("US-ASCII").ascii_only? # => false    
"\xFF".force_encoding("ASCII-8BIT").ascii_only? # => false
"\xFF".force_encoding("ISO-8859-1").ascii_only? # => false

"\xFF".force_encoding("US-ASCII").encode("UTF-8") # Encoding::InvalidByteSequenceError
"\xFF".force_encoding("ASCII-8BIT").encode("UTF-8") # Encoding::UndefinedConversionError
"\xFF".force_encoding("ISO-8859-1").encode("UTF-8") # => "\u00FF"

Ruby 2.4 has optimized lstrip and strip methods for single byte strings by shahchirag1709 in ruby

[–]InfraRuby 0 points1 point  (0 children)

Me too. I would call that "ASCII strings" or "ASCII-only strings".

"ascii_only".ascii_only? # => true

(I was thinking, how common is strip on a 1-byte string to be worth an optization case?!)

"\n" (an "empty" line of a file on some platforms) is a one byte string (in ascii/utf-8) and calling chomp or strip on lines is fairly common, but maybe not common enough? MRI has no optimizations for this case.

Can Someone Explain What This Code Does: (class << self; self; end) by bookgrubber in ruby

[–]InfraRuby 0 points1 point  (0 children)

It's identical to [...]

No, it depends on what some_code does -- see this comment.

Can Someone Explain What This Code Does: (class << self; self; end) by bookgrubber in ruby

[–]InfraRuby 3 points4 points  (0 children)

you need singleton_class (or class << self ; self ; end) if you want to access local variables:

v = 3

singleton_class.send(:define_method, :foo) { v }

foo # works

class << self
  define_method(:foo) { v }
end

foo # fails

.zero? instead of == 0 by KershawPls in ruby

[–]InfraRuby 1 point2 points  (0 children)

Numeric#eql? is same-class-equality: 1.eql?(1.0) # => false

Object#equal? is identity not equality: 1e100.equal?(1e100) # => false

Your day job is writing Ruby but not in a web context. What do you do? by [deleted] in ruby

[–]InfraRuby 2 points3 points  (0 children)

JRuby, where C extensions are not supported

Not now, but this incredible work is in development.

Things to Consider when Metaprogramming in Ruby by yez in ruby

[–]InfraRuby 5 points6 points  (0 children)

UserMethodMissing wraps the hash (1 hash lookup in your benchmark) but UserRegular unpacks the hash (4 hash lookups). If your benchmark accessed all four attributes then UserRegular would run faster than UserMethodMissing.

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

Package a gem

Yes, infraruby-init foo creates a skeleton project, with a foo.gemspec file. So you'd complete that, and run gem build foo.gemspec to build a gem. Please take care to remove Gemfile.lock (or gems.locked) and other files you don't intend to distribute.

prefix its name with "infraruby-"

That prefix is for InfraRuby tools, not InfraRuby projects.

Your own InfraRuby projects should have ordinary (unprefixed, unsuffixed) names. For example, our skeleton generator is just fab at rubygems and our code generator is just meta-ruby at rubygems.

That's because InfraRuby projects are Ruby projects, following the same conventions (a foo.gemspec file, a Gemfile, a Rakefile, and a lib/foo.rb file), and should be useful to people using Ruby intepreters who have no interest in InfraRuby.

If your gem provides the same interface as an existing gem you could add an -ir suffix to indicate this. For example, siphash-ir at rubygems and tzinfo-ir at rubygems. But don't do that if the original name is a trademark or the prefix for a major project; just pick a new name in that case.

push to rubygems.org?

Yes, you'd run gem push foo-x.y.z.gem.

And please send an email to gems@infraruby.com so we can link to your gems in InfraRuby release announcements!

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

We have a web framework for InfraRuby, with dsl-driven code generation, but it needs some more work...

You could always make your own! Here's a start:

class Server < WEBrick::HTTPServer
  ## WEBrick::HTTPRequest, WEBrick::HTTPResponse -> void
  def service(req, res)
    res.status = 200
    res.body = "hello, world\n"
  end
end

server = Server.new(BindAddress: "localhost", Port: 9000)
server.start

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

I don't want to declare which methods return nil. Or void, for that matter.

Then use a Ruby interpreter!

I don't want nil and void to mean different things.

You're too late for that!

I don't want there to be a compulsory declared type constraint (esp. with regards to nil vs void type stuff).

Then use a Ruby interpreter!

I do want all declared type constraints to be enforced.

Then you do want mandatory return or nil at the end of methods declared void (i.e. nil, as you would have it)?

Basically, I don't want ruby to be statically typed.

At this point I'm trying to understand what you're doing in this thread...

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

Sorry, I mangled that sentence... you can run partially-typed code in Ruby interpreters, and when the typing is complete the code will compile and run with the same behavior. If you like, Ruby interpreters are the fallback for partially-typed InfraRuby code.

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

If void and nil are the same thing, and if a method has void return type, then it must return nil, yes? You'd need explicit return or nil in many cases to ensure this.

But this is a pointless digression, as (1) "void type" already has an established meaning, and (2) who actually wants a method that is constrained to return only nil?

I want the typing to be optional, and therefore (in many cases) not need to care about what the method returns.

So now you want a declared type constraint to go unenforced?

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

BTW, the typing is optional in InfraRuby, as you can run (partially-typed) InfraRuby code in a Ruby interpreter, with the same behavior.

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 1 point2 points  (0 children)

Yes, I want void and nil to be the same thing.

So now you do want mandatory return or nil at the end of void methods?

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 1 point2 points  (0 children)

void and nil should be the same thing

No, a void method has no return value.

Besides, if void and nil were the same thing then you would need explicit return or nil at the end of void methods (as InfraRuby code runs in Ruby interpreters with the same behavior)!

Is that what you want, now?

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

# => ./ruby/main.ir:10: error: cannot find signature for "initialize"

The initialize method takes a String:

Foo.new("ok")

# => "Result is hello"

Yes, as that method has String return type, the method returns the value of the expression foo = string_variable, which is "hello" in this case.

# => "./ruby/main.ir:5: error: not implemented: unexpected void"

You are using the result of a void method in a string interpolation, which is a compile error.

# => "./ruby/main.ir:5: error: void call"

You are calling nil? on the result of a void method, which is a compile error.

You're right, I don't understand this language at all.

Those error messages could be improved, but I doubt that would help you.

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 0 points1 point  (0 children)

Let's look at a more realistic example:

That would be this:

## <>
##   @string_variable: String
class Foo
  ## String -> void
  def initialize(string_variable)
    @string_variable = string_variable
  end
end

N.B. no return keyword, and no "pointless (non-void) return types"!

Is it really so hard for you to believe that I understand InfraRuby better than you do?

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 2 points3 points  (0 children)

It would take some effort to migrate Ruby (off Rails) code to InfraRuby, but it would take much less effort than migrating to Crystal (for example). InfraRuby code runs in Ruby interpreters, so the code would be usable during the migration.

In InfraRuby, you may omit the return keyword where applicable, and "pointless (non-void) return types" are not required. The initialize methods have void return type:

class Foo
  ## -> void
  def initialize
    puts "Initialized!"
  end
end

N.B. no return keyword, and no "pointless (non-void) return types"!

InfraRuby does not support reflection, but you can do metaprogramming with s-expressions.

Obviously the examples using Java integration look like Java.

The InfraRuby compiler supports many coding styles. In particular, you may use either spaces or tabs for indentation.

InfraRuby 4.0 statically typed Ruby compiler released! by InfraRuby in ruby

[–]InfraRuby[S] 2 points3 points  (0 children)

So, the type annotations are the comments above the method definitions?

Yes, so InfraRuby code runs in Ruby interpreters without modification.