
My Weird Ruby - adamesque
http://awardwinningfjords.com/2015/03/03/my-weird-ruby.html
======
jfaucett
I'd also add that rubys confusion about what a function is is the thing that's
been annoying me the most lately. You have procs, lambdas, blocks, and all
with subtle differences ([http://awaxman11.github.io/blog/2013/08/05/what-is-
the-diffe...](http://awaxman11.github.io/blog/2013/08/05/what-is-the-
difference-between-a-block/)), and all I want are simple funcs as first class
citizens that have consistent behavior. (TCO as a default would also be nice).

"And finally, pie in the sky, can we solve packaging apps up into
distributable binaries, please? Rust and Go are making us look bad."

As a ruby programmer the lack of any reasonable - i.e. not hacky - way to
build binaries is annoying. Unless you're building a server side app, you can
pretty much forget using ruby because of this. Maybe that's all ruby cares
about, its certainly its niche but I like ruby and would like to be able to
use it for cli programs, etc. Personally, I don't want end users of my code to
have to install ruby, learn about ruby gems and boot the ruby vm before having
to run a cli program.

~~~
ramius345
I know this is in the vein of hacky solutions, but I tend to use jruby for the
purpose of packaging up ruby applications.

~~~
delsalk
Do you still require the JVM installed in the same way you would the Ruby's
VM?

~~~
ramius345
JRuby's ruby VM runs on top of whatever JVM you choose. You just have to make
sure you have the JVM in your path.

------
rubyn00bie
Some small but I think important nit-picky things about Struct

1.) A struct in ruby isn't just data, it is an object.

2.) Structs come with some weird gotchas, most notably that it is an
Enumerable!

3.) It's generally better to use a hash (in ruby) if you want "pure" data
object (and they at least used to be faster).

I myself have written a lot of "weird" Ruby and I will say that more often
than not it's detrimental to an application that is used/developed by others.
Often times ideas that seem brilliant in one language, cannot be translated
into another (immutability), and it's best to use the recommended paradigms.
Especially when those using the software are not familiar with them, and most
likely won't become familiar with them....

For me, many functional paradigms are just lost on ruby because it's so highly
mutable that practicing them is more academic than practical (sadly). That's
why I write Scala or Elixir now when I want/need those paradigms-- because
they're the right tools for that job.

I definitely don't want to discourage innovation, or bringing great ideas to
ruby from other places-- I just want to emphasize caution :)

~~~
grandalf
You can always freeze your hashes in Ruby for safety if you want to. All
that's missing is some sugar for declaring immutable hash literals. I guess
one way would be to allow clojure-style minimal punctuation map literals and
make them immutable...

~~~
masklinn
> ou can always freeze your hashes in Ruby for safety if you want to. All
> that's missing is some sugar for declaring immutable hash literals.

And immutable structures with efficient "updates". Because otherwise every
time you're altering the structure you have to copy it in full (though
shallowly) then mutate it in place.

~~~
grandalf
Well you could use this:

[https://github.com/hamstergem/hamster](https://github.com/hamstergem/hamster)

------
dkarapetyan
That's not that weird. After trying to learn Haskell and reading
"Understanding Computation" the Struct and enumerable style of structuring
code feels very natural.

I disagree with the conclusions though. Contracts and replacing `nil` with
`Maybe` doesn't sound right to me at all since I use `nil` pretty heavily all
over the place and the extra layer of `Maybe` doesn't buy me anything. I don't
understand what he means by a dependency system since Gems have their
dependencies spelled out pretty explicitly. Killing symbols is just silly
because I use them to tag all sorts of stuff and message passing with symbols
feels more natural than any other data type. Packaging could be better and
optional types would also be nice. I like how TypeScript does it actually
quite a lot.

~~~
codygman
> extra layer of `Maybe` doesn't buy me anything.

Wouldn't that layer be there all the time anyway? Either in the form of a sum
type (Just a | Nothing), explicit nil checking, or ignoring nil's and getting
a runtime error.

~~~
dkarapetyan
It's there with nil to begin with. A Maybe type without pattern matching is
basically nil checking. Now if he had said I want some kind of pattern
matching then I would get behind that.

~~~
codygman
So you would prefer a language without sum types but with pattern matching and
exhaustiveness checking for nil then?

~~~
dkarapetyan
Not what I said and I don't see why you make those choices mutually exclusive.
You can have pattern matching without sum types and you can have sum types
without pattern matching.

In fact Ruby's case/when statement is very limited form of pattern matching
that can be put to great use with proper use of Structs and overloading of
===.

~~~
masklinn
Erlang is probably a better example of pattern matching (complete) without
formal sum types (though dialyzer has value and type alternatives)

------
Roboprog
Mostly that was an interesting article, but there was one pain point: having
to read the parameter list to a routine _three_ (!) times.

Honestly, why has no language (few languages?) come up with a scheme yet to
put the formal parameters to a routine one per line, with documentation, like
so:

    
    
        ...
    

param-name [<type, if specified>] [<documentation>]

    
    
        ...
    

Swap the name and type order for "New Jersey" style languages vs "Swiss" style
languages as needed.

This is actually how I used to write out my C function headers (Frack K&R
layout!), even though we didn't use a doc generator tool such as Doxygen
(sp?).

Javadoc is only slightly less offensive, naming the parameters twice, due to
slavish adherence to the altar of New Jersey formatting. I would love to see
"//@ description..." after each parameter as an alternate to "* @param name
description..." duplication above the parameters. "WET brain-death forever!",
I guess.

~~~
kjs3
Can you show an example of your C header style? I confess I'm not quite sure I
follow you there.

~~~
Roboprog

        /* Return validated output for printing */
        static
        t_output *      val_and_xform
            (
            int         in_cnt     /* input item counter, 1 based */
            t_input *   raw_in     /* raw input, immutable, not null */
            )
            {
            ...
            }
    

Further examples:
[https://github.com/roboprog/buzzard/blob/master/bzrt/src/bzr...](https://github.com/roboprog/buzzard/blob/master/bzrt/src/bzrt_alloc.h)

~~~
kjs3
Ah, got it. That has a lot going for it, documentation wise. Thanks for the
illumination.

I can see the style-nazis hating on it with a white-hot fury, tho.

------
grandalf
That Ruby looks excellent. I hadn't realized the contracts gem existed.

So much of what people redundantly cram into test suites could be handled with
simple contracts.

~~~
bshimmin
If, like me, you were wondering how contracts.ruby works, the comments in here
are quite instructive:
[https://github.com/egonSchiele/contracts.ruby/blob/master/li...](https://github.com/egonSchiele/contracts.ruby/blob/master/lib/contracts/decorators.rb)

~~~
grandalf
very cool.

------
phamilton
I'd be really interested to see success typing applied to ruby.

[http://user.it.uu.se/~kostis/Papers/succ_types.pdf](http://user.it.uu.se/~kostis/Papers/succ_types.pdf)

TL/DR: Success typing considers all possible types a value can have. If a
function returns either a bool or an int and you then pass that value into a
function that accepts a string or an int, then the success typing checks out.
It doesn't mean your program is correct, but that it could possibly be
correct. On the other hand, if you pass the "bool or int" value into a
function that only accepts a string, the type checker will complain and you
know for sure your program is incorrect. In other words, you will get false
negatives but never a false positive.

~~~
marvy
But how do you know what the function only accepts a string in a dynamic,
duck-typed language?

~~~
Smfranz
Ruby is not a duck-typed language. "duck-typing" is only touted by its
community to award it free credibility and merit where there is none. "duck-
typing" is essentially free for any dynamic typed language which have method
RTTI. So please, stop the "duck-typing" pride parade. It is nauseating.

~~~
marvy
Huh? If Ruby is not duck-typed, can you give me an example of a something that
is? It seems like the textbook example. Here are two weird examples: 1\. C++
templates and 2) C# variables declared dynamic (I don't know C#, could be
wrong) Are we using the same definitions as each other?

~~~
phamilton
I think the point is that duck-typing in Ruby is less of a feature and more of
an inevitability due to its dynamic RTTI nature.

Compare that to duck-typing in Go where it was a very deliberate design
decision.

~~~
djur
Duck typing generally refers exclusively to runtime type checking (i.e.
dynamically-typed languages). What Go does is structural typing.

~~~
marvy
I disagree. C++ templates for instance are also duck-typed, but they act at
compile time, not run time.

------
wasd
Traveling Ruby is a good way to package ruby applications.
[https://github.com/phusion/traveling-
ruby](https://github.com/phusion/traveling-ruby)

~~~
MrBra
but you can't yet build Windows binaries ON Windows

------
pje
Ruby's cardinal sin: there's no way to `require` code without global side
effects.

e.g.
[https://twitter.com/tomdale/status/457282269342744576](https://twitter.com/tomdale/status/457282269342744576)

~~~
xentronium
One man's sin is another's superpower.

~~~
yxhuvud
Yes, which is why having the ability to do both would be nice.

------
Veedrac
If you want to replace floats, what with?

Symbolic computation is way too expensive.

Fractions are good whilst they're restricted in size but are too slow at
arbitrary precision and too inaccurate with numbers not centred on 1.

Fixed precision decimal floating point has numerical problems because numbers
scale by too large an increment. (see footnote)

Arbitrary precision floats don't solve anything unless your problem was too
little precision - with the precision of a 64 bit float this is rarely the
case and 128 bits is massively more than that.

Arbitrary precision decimals don't solve anything either.

Logarithmic number systems are a good contender but almost all operations
become lossy. This is OK if you're using them as approximations - which is the
common use of floats - but the fact floats are exact on the integers up to a
large ceiling is useful (see Javascript) as with many other of their exactness
properties.

Even better might be a symmetric level-index number system; you get the
advantages of logarithmic number systems but _also_ get immunity from overflow
and underflow - the only operation that isn't closed is division by 0 and
since operations can't underflow _all_ 0s are actually 0.

If it were me implementing a new very-high level language with only weak cares
about speed (eg. faster than doing it symbolically), I'd probably choose to
use fixed precision fractions that fall back to symmetric level-index numbers
instead of rounding. That way I'd get precise rationals (including int64s),
immunity from underflow and overflow and a smoother error curve than floats.

\---

Some people are pretty surprised to hear me criticize decimal types, but
they're genuinely numerically worse than binary floating point. I've talked
about this in depth here:

[http://www.reddit.com/r/programming/comments/2ut00j/a_little...](http://www.reddit.com/r/programming/comments/2ut00j/a_little_thing_to_love_about_perl_6_and_cobol/cobl3vd)

and I give a rough rule-of-thumb about what type to use when here:

[http://www.reddit.com/r/learnpython/comments/2wyeho/is_this_...](http://www.reddit.com/r/learnpython/comments/2wyeho/is_this_an_error_in_the_python_interpreter_if_not/covafmk)

------
sshaw
Really, that's not weird at all. Far from it.

For a truly different Ruby coding style checkout some of Ara T. Howard's code:
[https://github.com/ahoward](https://github.com/ahoward).

------
lancefisher
Why kill symbols?

~~~
bigtunacan
I was wondering this as well. Symbols are just atoms and atoms are great. The
biggest issue with symbols in ruby is how gc is handled and that has improved
in recent releases.

~~~
TylerJay
thirded. Can someone who doesn't like symbols help me understand the downsides
of them? I really like how natural it makes passing around params that can be
one of {x1,x2,x3...,xn} different values. Accomplishing the same with strings
just feels messier and more prone to error.

~~~
bigtunacan
The only problem with Ruby's implementation of symbols was possibility of DoS
which is resolved through garbage collection in the latest Ruby.

Something that I found a bit ironic about the video linked in the article is
at 5 mins 30 secs in; he states, "Why not give the memory address a name that
makes sense to a person?" Here is referring to assembly and the abstraction it
makes and how this relates to the abstraction that is variables. Symbols are
really a cross system immutable memory address abstraction; I don't see how
this is a bad thing.

------
unknownian
Is Rubinius X still a thing?

------
jrochkind1
Is there an ETA for middleman 4.0?

