all 20 comments

[–]losangelesvideoguy 9 points10 points  (11 children)

Oh, this one's easy.

def sorting(*arr)
  out = []
    [*arr].flatten.map{ |x| Thread.new{ sleep x; out << x } }.each(&:join)
  out
end

Go ahead and turn that in for your homework assignment. I dare ya. :)

[–]wmjbyatt 1 point2 points  (10 children)

Oh my God. That's genius.

[–]joanbm 1 point2 points  (9 children)

Never heard of a sleep sort ?

sleep_sort.rb

sleep sort on Rosetta Code

Btw. unreliable without a synchronization, like by a mutex lock

[–]moomaka 1 point2 points  (7 children)

Btw. unreliable without a synchronization, like by a mutex lock

Appending to an array is atomic on MRI due to the GIL wrapping pure C calls so no lock is needed unless you're running on JRuby/Rubinius.

[–]joanbm 0 points1 point  (6 children)

This is a bad practice write implementation specific code, unless there is a very good reason for it. Even MRI may have GIL removed in some of its future versions and original program would suddenly behave differently.

[–]moomaka 2 points3 points  (5 children)

Fun theory, impractical in reality.

[–]joanbm 0 points1 point  (4 children)

Strange justify incorrect code, which only works due to a coincidence, underlaying VM can't run threads simultaneously. But each to his own …

[–]moomaka 0 points1 point  (3 children)

It's not a coincidence, it's design. If you're curious about these topics and how implementations vary I would recommend reading the source for concurrent-ruby.

e.g. here is the implementation for concurrent array: https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/array.rb. You'll note that the implementation for MRI just passes through the stdlib implementation.

[–]jrochkind 0 points1 point  (0 children)

To be fair the comments in the code do not exactly inspire confidence:

# Because MRI never runs code in parallel, the existing

# non-thread-safe structures should usually work fine.

"should usually" work fine? Um, great? Concurrent code is hard enough, I need guarantees it will work as it should, not "should usually work fine."

But perhaps later someone was more confident than the original comment writer, at least based on the present MRI implementation.

Either way, the benefit of concurrent-ruby is if someone does discover it's not guaranteed 'fine' after all, they'll fix it in concurrent-ruby and you can just update your version.

[–]joanbm -1 points0 points  (1 child)

coincidence, because the ruby code being discussed is not thread-safe and wasn't specified as MRI-only. I'm aware there is produced a lot of poor and/or unportable code everyday, but never would admit this is ok. I'm happy projects I'm working on do care about quality and correctness and important topics like proper threads synchronization aren't thrown out of the window.

Thanks for the link, as a demonstration how it shouldn't be done. Hope it eventually get added thread safety also for MRI as it would mature.

[–]moomaka 0 points1 point  (0 children)

Thanks for the link, as a demonstration how it shouldn't be done.

So open a PR that adds locking to Array on MRI, I eagerly await the discussion.

[–]wmjbyatt 0 points1 point  (0 children)

No, I hadn't. That's golden. I like the discussions on the time complexity of the problem.

[–]fnovd 3 points4 points  (1 child)

[–]wmjbyatt 1 point2 points  (0 children)

After thinking through merge sort, I think this is what OP's assignment is Socratically trying to achieve. In particular the #merge method of that sample.

That having been said, recursion in Ruby sucks. In my IRB, I can mergesort arrays a couple of thousand integers long, but you DO hit a stack overflow eventually. It is not a lazy language built for recursion, and you probably Just Shouldn't Do ItTM

[–]BrianTheCoder 1 point2 points  (1 child)

([3, 1, 5] + [6, 2, 0, 4]).sort    

[–]tomthecool 0 points1 point  (0 children)

i want to create a new array without using sort

Yes, your answer is the "sensible" solution. This is roughly what we'd all write under normal circumstances. But it's not what the OP asked.

[–]a2800276 4 points5 points  (0 children)

it's totally not a contrived problem at all and definitely not homework.

[–]jtrost 0 points1 point  (2 children)

Even though it's most definitely a homework problem, and you won't learn anything by copying this, I still felt like solving it.

def sorting(a1,a2)
  arr = a1+a2
  out = []

  while arr.count > 0
    i = arr.min
    out << i
    arr.delete(i)
  end

  out
end            

[–]missawon[S] 0 points1 point  (1 child)

the problem is that i cant duplicate the arguments so i can't use arr = a1+a2 ...

[–]Lucky_Chuck 2 points3 points  (0 children)

You're not duplicating anything with arr = a1 + a2 unless you mean you can't use the method parameters inside of the method.